Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 7 additions & 3 deletions src/frameworks/flutter/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { readFile } from "fs/promises";

import { BuildResult, Discovery, FrameworkType, SupportLevel } from "../interfaces";
import { FirebaseError } from "../../error";
import { assertFlutterCliExists } from "./utils";
import { assertFlutterCliExists, getTreeShakeFlag } from "./utils";
import { DART_RESERVED_WORDS, FALLBACK_PROJECT_NAME } from "./constants";

export const name = "Flutter Web";
Expand Down Expand Up @@ -50,9 +50,13 @@ export function init(setup: any, config: any) {
return Promise.resolve();
}

export function build(cwd: string): Promise<BuildResult> {
export async function build(cwd: string): Promise<BuildResult | undefined> {
Comment thread
emwp marked this conversation as resolved.
Outdated
assertFlutterCliExists();
const build = spawnSync("flutter", ["build", "web"], { cwd, stdio: "inherit" });

const otherArgs = await getTreeShakeFlag();
const buildArgs = ["build", "web", otherArgs].filter(Boolean);

const build = spawnSync("flutter", buildArgs, { cwd, stdio: "inherit" });
if (build.status !== 0) throw new FirebaseError("Unable to build your Flutter app");
return Promise.resolve({ wantsBackend: false });
}
Expand Down
55 changes: 52 additions & 3 deletions src/frameworks/flutter/utils.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@ import * as sinon from "sinon";
import { EventEmitter } from "events";
import { Writable } from "stream";
import * as crossSpawn from "cross-spawn";

import { assertFlutterCliExists } from "./utils";
import * as yaml from "yaml";
import { assertFlutterCliExists, getTreeShakeFlag } from "./utils";
import * as fs from "fs";

describe("Flutter utils", () => {
describe("assertFlutterCliExists", () => {
Expand All @@ -25,10 +26,58 @@ describe("Flutter utils", () => {
process.stderr = new EventEmitter();
process.status = 0;

const stub = sandbox.stub(crossSpawn, "sync").returns(process as any);
const stub = sandbox.stub(crossSpawn, "sync").returns(process);

expect(assertFlutterCliExists()).to.be.undefined;
sinon.assert.calledWith(stub, "flutter", ["--version"], { stdio: "ignore" });
});
});

describe("getTreeShakeFlag", () => {
let sandbox: sinon.SinonSandbox;

beforeEach(() => {
sandbox = sinon.createSandbox();
});

afterEach(() => {
sandbox.restore();
});

it("should return '--no-tree-shake-icons' if a tree shake package is found", async () => {
const pubSpecContent = `
dependencies:
material_icons_named: any
`;
const readFileStub = sandbox.stub(fs, "readFile").resolves(Buffer.from(pubSpecContent));
const yamlParseStub = sandbox.stub(yaml, "parse").returns({
dependencies: {
material_icons_named: "any",
},
});

const result = await getTreeShakeFlag();
expect(result).to.equal("--no-tree-shake-icons");
sinon.assert.calledOnce(readFileStub);
sinon.assert.calledOnce(yamlParseStub);
});

it("should return an empty string if no tree shake package is found", async () => {
const pubSpecContent = `
dependencies:
some_other_package: any
`;
const readFileStub = sandbox.stub(fs, "readFile").resolves(Buffer.from(pubSpecContent));
const yamlParseStub = sandbox.stub(yaml, "parse").returns({
dependencies: {
some_other_package: "any",
},
});

const result = await getTreeShakeFlag();
expect(result).to.equal("");
sinon.assert.calledOnce(readFileStub);
sinon.assert.calledOnce(yamlParseStub);
});
});
});
26 changes: 26 additions & 0 deletions src/frameworks/flutter/utils.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { sync as spawnSync } from "cross-spawn";
import { FirebaseError } from "../../error";
import { readFile } from "fs/promises";
import * as yaml from "yaml";

export function assertFlutterCliExists() {
const process = spawnSync("flutter", ["--version"], { stdio: "ignore" });
Expand All @@ -8,3 +10,27 @@ export function assertFlutterCliExists() {
"Flutter CLI not found, follow the instructions here https://docs.flutter.dev/get-started/install before trying again.",
);
}

export async function getTreeShakeFlag(): Promise<string> {
Comment thread
leoortizz marked this conversation as resolved.
Outdated
const pubSpecPath = "./pubspec.yaml";
let pubSpec: Record<string, any> = {};
try {
const pubSpecBuffer = await readFile(pubSpecPath);
Comment thread
leoortizz marked this conversation as resolved.
Outdated
pubSpec = yaml.parse(pubSpecBuffer.toString());
} catch (error) {
console.info("pubspec.yaml not found, skipping tree shaking");
return "";
}

const treeShakePackages = [
"material_icons_named",
"material_symbols_icons",
"material_design_icons_flutter",
"flutter_iconpicker",
"font_awesome_flutter",
"ionicons_named",
];
Comment thread
emwp marked this conversation as resolved.

const hasTreeShakePackage = treeShakePackages.some((pkg) => pubSpec.dependencies?.[pkg]);
return hasTreeShakePackage ? "--no-tree-shake-icons" : "";
}