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
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
|
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",
"node/zlib.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),
"$lazy": "$$BUN_LAZY$$",
},
} as const;
const productionOpts = {
...opts,
define: {
...opts.define,
"IS_BUN_DEVELOPMENT": "false",
},
};
const devOpts = {
...opts,
define: {
...opts.define,
"IS_BUN_DEVELOPMENT": "true",
},
};
const build_prod_minified = await Bun.build({
entrypoints: entrypoints.filter(file => minifyList.includes(file.slice(import.meta.dir.length + 1))),
minify: true,
...productionOpts,
});
const build_prod_unminified = await Bun.build({
entrypoints: entrypoints.filter(file => !minifyList.includes(file.slice(import.meta.dir.length + 1))),
minify: { syntax: true },
...productionOpts,
});
const build_dev = await Bun.build({
entrypoints: entrypoints,
minify: { syntax: true },
sourcemap: "external",
...devOpts,
});
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, "")
.replace(/\$\$BUN_LAZY\$\$/g, 'globalThis[Symbol.for("Bun.lazy")]');
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`);
|