Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(main-app): change main app to esbuild #1678

Merged
merged 5 commits into from
Sep 20, 2022
Merged
Show file tree
Hide file tree
Changes from all 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
4 changes: 4 additions & 0 deletions cspell.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ module.exports = {
"submenu",
"unhide",
"nsis",
"respawn",

// file type
"avif",
Expand Down Expand Up @@ -162,6 +163,9 @@ module.exports = {
// vscode
"dbaeumer",
"keystyle",

// esbuild config
"metafile",
],
flagWords: ["fuck", "bitch", "asshole", "bullshit", "crap", "suck", "wtf"],
dictionaries: [
Expand Down
10 changes: 8 additions & 2 deletions desktop/main-app/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,16 @@
"url": "https://github.com/netless-io/flat"
},
"scripts": {
"start": "cross-env NODE_ENV=development webpack --config webpack/webpack.dev.js",
"_start": "cross-env NODE_ENV=development webpack --config webpack/webpack.dev.js",
"start:cn": "cross-env FLAT_REGION=CN pnpm start",
"start:us": "cross-env FLAT_REGION=US pnpm start",
"build": "cross-env NODE_ENV=production webpack --config webpack/webpack.prod.js",
"_start:esbuild": "esbuild-dev --cjs scripts/esbuild/esbuild.dev.ts",
"start": "cross-env NODE_ENV=development pnpm run _start:esbuild",
"_build": "cross-env NODE_ENV=production webpack --config webpack/webpack.prod.js",
"build:cn": "cross-env FLAT_REGION=CN pnpm build",
"build:us": "cross-env FLAT_REGION=US pnpm build",
"_build:esbuild": "esbuild-dev --cjs scripts/esbuild/esbuild.prod.ts",
"build": "cross-env NODE_ENV=production pnpm run _build:esbuild",
"build:debug": "cross-env FLAT_DEBUG=debug webpack --config webpack/webpack.debug.js",
"pack:win": "node ./scripts/pack win",
"pack:mac": "node ./scripts/pack mac",
Expand All @@ -28,7 +32,9 @@
"_launch:electron": "node --trace-uncaught ./scripts/launch/electron.js"
},
"devDependencies": {
"@types/dotenv-flow": "^3.2.0",
"@types/webpack-env": "^1.16.3",
"dotenv-flow": "^3.2.0",
"dotenv-flow-webpack": "^1.1.0",
"electron": "12.0.15",
"electron-builder": "^23.0.3",
Expand Down
15 changes: 15 additions & 0 deletions desktop/main-app/scripts/esbuild/esbuild.common.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { autoChooseConfig } from "../../../../scripts/utils/auto-choose-config";
import pkg from "../../package.json";
import dotEnvFlowPlugin from "./plugin/dotEnvFlowPlugin";
import { replaceImportMeta } from "./plugin/replaceImportMeta";

export const external = Object.keys(pkg.dependencies);

export const dotenvPlugin = dotEnvFlowPlugin({
path: autoChooseConfig(),
system_vars: true,
default_node_env: "development",
silent: true,
});

export const replaceMetaPlugin = replaceImportMeta();
52 changes: 52 additions & 0 deletions desktop/main-app/scripts/esbuild/esbuild.dev.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import { ChildProcess, spawn } from "child_process";
import esbuild from "esbuild";
import { dotenvPlugin, external, replaceMetaPlugin } from "./esbuild.common";
import * as paths from "./paths";

let child: ChildProcess | undefined;
const respawn = () => {
if (child) {
child.kill("SIGTERM");
}
child = spawn("pnpm", ["electron", paths.dist], { stdio: "inherit" });
};

const buildPreload = esbuild.build({
entryPoints: [paths.preloadPath],
bundle: true,
platform: "browser",
target: "chrome89",
external: [...external, "electron", "os", "path"],
outfile: paths.preloadDist,
watch: true,
});

const buildMain = esbuild.build({
entryPoints: [paths.entryFile],
bundle: true,
platform: "node",
target: "node14",
external: [...external, "electron", "electron-devtools-vendor"],
sourcemap: true,
outfile: paths.dist,
watch: {
onRebuild(error) {
if (error) {
console.error("watch build failed:", error);
} else {
respawn();
}
},
},
plugins: [dotenvPlugin, replaceMetaPlugin],
});

const allDone = Promise.all([buildPreload, buildMain]);

const stop = () =>
allDone.then(rs => rs.forEach(r => r.stop && r.stop())).catch(() => process.exit(1));

process.on("SIGINT", stop);
process.on("SIGTERM", stop);

allDone.then(respawn);
26 changes: 26 additions & 0 deletions desktop/main-app/scripts/esbuild/esbuild.prod.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import esbuild from "esbuild";
import { dotenvPlugin, external } from "./esbuild.common";
import * as paths from "./paths";

const buildPreload = esbuild.build({
entryPoints: [paths.preloadPath],
bundle: true,
platform: "browser",
target: "chrome89",
external: [...external, "electron", "os", "path"],
outfile: paths.preloadDist,
plugins: [dotenvPlugin],
});

const buildMain = esbuild.build({
entryPoints: [paths.entryFile],
bundle: true,
platform: "node",
target: "node14",
hyrious marked this conversation as resolved.
Show resolved Hide resolved
external: [...external, "electron", "electron-devtools-vendor"],
sourcemap: true,
outfile: paths.dist,
plugins: [dotenvPlugin],
});

Promise.all([buildPreload, buildMain]).catch(() => process.exit(1));
9 changes: 9 additions & 0 deletions desktop/main-app/scripts/esbuild/paths.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import path from "path";

const resolvePath = (...relativePath: string[]): string =>
path.resolve(__dirname, "..", "..", ...relativePath);

export const dist = resolvePath("dist", "main.js");
export const preloadDist = resolvePath("dist", "preload.js");
export const entryFile = resolvePath("src", "index.ts");
export const preloadPath = resolvePath("src", "preload.ts");
58 changes: 58 additions & 0 deletions desktop/main-app/scripts/esbuild/plugin/dotEnvFlowPlugin.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import { Plugin, PluginBuild } from "esbuild";
import dotenvFlow, { DotenvConfigOptions } from "dotenv-flow";

function parseWithEnvObject(orgEnv: Record<string, string | undefined>): Record<string, string> {
return Reflect.ownKeys(orgEnv)
?.map(item => {
const result: Record<string, any> = {};
if (typeof item === "string" && orgEnv?.[item]) {
result[`process.env.${item}`] = JSON.stringify(orgEnv?.[item]);
}
return result;
})
?.reduce((prev, cur) => {
return {
...prev,
...cur,
};
}, {});
}

// Configuration define refer to https://github.com/kerimdzhanov/dotenv-flow-webpack
type DotEnvPluginOptionsType = Omit<DotenvConfigOptions, "purge_dotenv"> & {
system_vars?: boolean;
};

type DotEnvPluginType = (options: DotEnvPluginOptionsType) => Plugin;

const dotEnvFlowPlugin: DotEnvPluginType = options => {
return {
name: "DotEnvFlow",
setup(build: PluginBuild) {
let sysEnvList = {};

const esbuildOptions = build.initialOptions;

const result = dotenvFlow.config(options);

if (result.error) {
console.warn("esbuild dotenvFlow throw error:", result.error);
return;
}

if (options?.system_vars) {
sysEnvList = parseWithEnvObject(process.env);
}

const configEnvList = parseWithEnvObject(result?.parsed || {});

esbuildOptions.define = {
...esbuildOptions?.define,
...sysEnvList,
...configEnvList,
};
},
};
};

export default dotEnvFlowPlugin;
37 changes: 37 additions & 0 deletions desktop/main-app/scripts/esbuild/plugin/replaceImportMeta.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { Plugin } from "esbuild";
import { readFile } from "fs-extra";
import { dirname } from "path";
import { pathToFileURL } from "url";

export interface ReplaceImportMetaOptions {
/**
* Passed to `onLoad()`.
* @default /\.[jt]s$/
*/
filter?: RegExp;
}

/**
* Replace `import.meta.url` and `__dirname`, `__filename` with absolute path.
* Taken from https://github.com/vitejs/vite/blob/main/packages/vite/src/node/config.ts
*/
export function replaceImportMeta(options: ReplaceImportMetaOptions = {}): Plugin {
const filter = options.filter ?? /\.[jt]s$/;

return {
name: "replace-import-meta",
setup({ onLoad }) {
onLoad({ filter }, async args => {
const contents = await readFile(args.path, "utf8");
const import_meta_url = JSON.stringify(pathToFileURL(args.path).href);
return {
loader: "default",
contents: contents
.replace(/\bimport\.meta\.url\b/g, import_meta_url)
.replace(/\b__dirname\b/g, JSON.stringify(dirname(args.path)))
.replace(/\b__filename\b/g, JSON.stringify(args.path)),
};
});
},
};
}
4 changes: 2 additions & 2 deletions desktop/main-app/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"compilerOptions": {
"target": "es2017",
"module": "CommonJS",
"lib": ["es2017", "DOM"]
"lib": ["es2017", "DOM"],
},
"include": ["src/**/*.ts", "typings/*.ts"]
"include": ["src/**/*.ts", "typings/*.ts", "scripts/**/*.ts"]
}
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
"devDependencies": {
"@commitlint/cli": "^17.0.0",
"@commitlint/config-angular": "^17.0.0",
"@hyrious/esbuild-dev": "^0.7.6",
"@hyrious/esbuild-dev": "^0.8.3",
"@netless/eslint-plugin": "^2.0.0",
"@types/fs-extra": "^9.0.13",
"@types/lodash-es": "^4.17.6",
Expand Down
Loading