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
114
|
import { BuildConfig } from "bun";
import fs from "fs";
import path from "path";
const OUT_DIR = path.join(import.meta.dir, "out/");
const TMP_DIR = path.join(import.meta.dir, "out/tmp");
// Because we do not load sourcemaps, we are not enabling identifiers + whitespace
// minification on all files, just on the ones without logic or were already bundled
const minifyList = [
"node/stream.js",
"node/crypto.js",
"node/assert.js",
"node/assert.strict.js",
"node/fs.promises.ts",
"node/path.js",
"node/path.posix.js",
"node/path.win32.js",
"node/stream.promises.js",
"node/stream.consumers.js",
"node/stream.web.js",
"node/url.js",
];
if (fs.existsSync(OUT_DIR + "/modules")) {
fs.rmSync(OUT_DIR + "/modules", { recursive: true });
}
if (fs.existsSync(OUT_DIR + "/modules_dev")) {
fs.rmSync(OUT_DIR + "/modules_dev", { recursive: true });
}
function readdirRecursive(root: string): string[] {
const files = fs.readdirSync(root, { withFileTypes: true });
return files.flatMap(file => {
const fullPath = path.join(root, file.name);
return file.isDirectory() ? readdirRecursive(fullPath) : fullPath;
});
}
const entrypoints = ["./bun", "./node", "./thirdparty"]
.flatMap(dir => readdirRecursive(path.join(import.meta.dir, dir)))
.filter(file => file.endsWith(".js") || (file.endsWith(".ts") && !file.endsWith(".d.ts")));
const opts = {
target: "bun",
naming: {
entry: "[dir]/[name].[ext]",
},
root: import.meta.dir,
define: {
"process.platform": JSON.stringify(process.platform),
"process.arch": JSON.stringify(process.arch),
},
} as const;
const build_prod_minified = await Bun.build({
entrypoints: entrypoints.filter(file => minifyList.includes(file.slice(import.meta.dir.length + 1))),
minify: true,
...opts,
});
const build_prod_unminified = await Bun.build({
entrypoints: entrypoints.filter(file => !minifyList.includes(file.slice(import.meta.dir.length + 1))),
minify: { syntax: true },
...opts,
});
const build_dev = await Bun.build({
entrypoints: entrypoints,
minify: { syntax: true },
sourcemap: "external",
...opts,
});
for (const [build, outdir] of [
[build_dev, path.join(OUT_DIR, "modules_dev")],
[build_prod_minified, path.join(OUT_DIR, "modules")],
[build_prod_unminified, path.join(OUT_DIR, "modules")],
] as const) {
if (!build.success) {
console.error("Build failed");
throw new AggregateError(build.logs);
}
if (build.logs.length) {
console.log("Build has warnings:");
for (const log of build.logs) {
console.log(log);
}
}
for (const output of build.outputs) {
fs.mkdirSync(path.join(outdir, path.dirname(output.path)), { recursive: true });
if (output.kind === "entry-point" || output.kind === "chunk") {
const transformedOutput = (await output.text()).replace(/^(\/\/.*?\n)+/g, "");
if (transformedOutput.includes("$bundleError")) {
// attempt to find the string that was passed to $bundleError
const match = transformedOutput.match(/(?<=\$bundleError\(")(?:[^"\\]|\\.)*?(?="\))/);
console.error(`Build ${output.path} $bundleError: ${match?.[0] ?? "unknown"}`);
console.error(`DCE should have removed this function call, but it was not.`);
process.exit(1);
}
Bun.write(path.join(outdir, output.path), transformedOutput);
} else {
Bun.write(path.join(outdir, output.path), output);
}
}
}
console.log(`Bundled esm modules in ${performance.now().toFixed(2)}ms`);
|