summaryrefslogtreecommitdiff
path: root/bs5/client/build.mjs
blob: f98de635d3466d5cf5ef49ea5009a6afb5b4d702 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
import Esbuild from "esbuild";
import Path from "path";
import { plugin as extractClientComponents } from "../packages/extract-client-components/esbuild-plugin.mjs";

async function build(entryPoints, { env, output, extract, mockWebpackRequire }) {
	const outfile = output;
	const outdir = Path.dirname(outfile);
	const splitting = true;

	const bootstrapOutput = Path.join(Path.dirname(outfile), "bootstrap.js");

	let plugins = [];
	if (extract) {
		plugins.push(
			extractClientComponents({
				target: "app",
				mockWebpackRequire,
				bootstrapOutput,
			}),
		);
	}

	const isDev = env === "development";

	try {
		const result = await Esbuild.build({
			entryPoints,
			entryNames: "[name]",
			bundle: true,
			logLevel: "debug",
			platform: "browser",
			format: "esm",
			splitting,
			outdir,
			plugins,
			write: true,
			treeShaking: isDev ? false : true,
			minify: isDev ? false : true,
			define: {
				"process.env.NODE_ENV": `"${env}"`,
				"__DEV__": `"${isDev}"`, /* __DEV__ is used by react-client code */
			},
		});

		entryPoints.forEach((entryPoint) => {
			console.log('Build completed successfully for "' + entryPoint + '"');
		});
		return result;
	} catch (error) {
		console.error("\nBuild failed:", error);
		process.exit(1);
	}
}

function parseArgv(argv) {
	const args = argv.slice(2);
	const result = { _: [] };

	for (let i = 0; i < args.length; i++) {
		const arg = args[i];

		if (arg.startsWith("--")) {
			const longArg = arg.slice(2);
			if (longArg.includes("=")) {
				const [key, value] = longArg.split("=");
				result[key] = parseValue(value);
			} else if (i + 1 < args.length && !args[i + 1].startsWith("-")) {
				result[longArg] = parseValue(args[++i]);
			} else {
				result[longArg] = true;
			}
		} else if (arg.startsWith("-")) {
			const shortArg = arg.slice(1);
			if (shortArg.includes("=")) {
				const [key, value] = shortArg.split("=");
				result[key] = parseValue(value);
			} else if (i + 1 < args.length && !args[i + 1].startsWith("-")) {
				result[shortArg] = parseValue(args[++i]);
			} else {
				for (const char of shortArg) {
					result[char] = true;
				}
			}
		} else {
			result._.push(parseValue(arg));
		}
	}

	return result;
}

function parseValue(value) {
	if (value === "true") return true;
	if (value === "false") return false;
	if (value === "null") return null;
	if (!isNaN(value)) return Number(value);
	return value;
}

function camelCaseKeys(obj) {
	return Object.fromEntries(
		Object.entries(obj).map(([key, value]) => [
			key.replace(/-([a-z])/g, (_, letter) => letter.toUpperCase()),
			value,
		]),
	);
}

const flags = parseArgv(process.argv);
const options = camelCaseKeys(flags);
const entryPoints = options._;

build(entryPoints, options);