-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathbuild.ts
More file actions
111 lines (109 loc) · 3.19 KB
/
build.ts
File metadata and controls
111 lines (109 loc) · 3.19 KB
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
import { Glob, Transpiler, fileURLToPath, pathToFileURL } from "bun";
import { basename, join, parse, relative } from "node:path";
export async function build({
baseDir,
buildDir = ".build",
pageDir = "pages",
hydrate,
sourcemap,
minify = Bun.env.NODE_ENV === "production",
define,
plugins,
onLoadPageFile = async ({ path, loader }) => {
const contents = await Bun.file(path).text();
return {
contents: contents.replaceAll(
/\/\/\s*@server-side[^\n\S]*\n[^\n]+\n/g,
""
),
loader,
};
},
}: {
baseDir: string;
buildDir?: string;
pageDir?: string;
hydrate: string;
sourcemap?: "external" | "none" | "inline";
minify?: boolean;
define?: Record<string, string>;
plugins?: import("bun").BunPlugin[];
onLoadPageFile?: import("bun").OnLoadCallback;
}) {
const entrypoints = [join(baseDir, hydrate)];
const absPageDir = join(baseDir, pageDir);
const entrypointGlob = new Glob("**/*.{ts,tsx,js,jsx}");
for await (const path of entrypointGlob.scan({
cwd: absPageDir,
onlyFiles: true,
absolute: true,
})) {
entrypoints.push(path);
}
const outdir = join(baseDir, buildDir);
const result = await Bun.build({
entrypoints,
sourcemap,
target: "browser",
outdir,
splitting: true,
minify,
define: {
"process.env.NODE_ENV": JSON.stringify(Bun.env.NODE_ENV || "development"),
...define,
},
plugins: [
{
name: "bun-react-ssr",
target: "browser",
setup(build) {
build.onResolve(
{ filter: new RegExp(`^${RegExp.escape(absPageDir)}/.*\\.ts[x]$`) },
async ({ importer, path }) => {
const url = pathToFileURL(importer);
return {
path: fileURLToPath(new URL(path, url)),
namespace: "client",
};
}
);
build.onLoad(
{ namespace: "client", filter: /\.ts[x]$/ },
onLoadPageFile
);
},
},
...(plugins ?? []),
],
});
if (result.success) {
const transpiler = new Transpiler({ loader: "js" });
const hashed: Record<string, string> = {};
const dependencies: Record<string, string[]> = {};
for (const output of result.outputs) {
const path = relative(outdir, output.path);
if (output.kind === "entry-point" && output.hash) {
hashed[`/${path}`] = output.hash;
const imports = transpiler.scanImports(await output.text());
dependencies[`/${hashremap(path, output.hash)}`] = imports
.filter((x) => x.kind === "import-statement")
.map((x) => "/" + join(path, "..", x.path));
}
if (output.kind === "chunk") {
const imports = transpiler.scanImports(await output.text());
dependencies[`/${path}`] = imports
.filter((x) => x.kind === "import-statement")
.map((x) => "/" + join(path, "..", x.path));
}
}
Bun.write(
join(outdir, ".meta.json"),
JSON.stringify({ version: 2, hashed, dependencies })
);
}
return result;
}
function hashremap(input: string, hash: string) {
const parsed = parse(input);
return `${join(parsed.dir, parsed.name)}-${hash}${parsed.ext}`;
}