-
Notifications
You must be signed in to change notification settings - Fork 5
/
build.ts
81 lines (70 loc) · 2.63 KB
/
build.ts
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
import "colors"
import { readdir } from "fs/promises"
import { resolve } from "path"
import { createReference, log } from "./utils"
log("Cleaning build artifacts")
log("Successful clean?".dim, (await Bun.$`rm -rf ./build/`).exitCode === 0)
// Here we'll store some data about the build process
const meta = { pages: { static: new Array<string>(), dynamic: new Array<string>() } }
const entries = (await readdir(resolve("src"), { recursive: true })).reduce(
(acc, file) => {
const ext = file.match(/\..+$/)
if (!ext) return acc
const path = resolve("src", file)
if (file.endsWith("page.tsx")) acc["pages"].push(path)
else if (ext[0].match(/\.tsx?$/)) acc["components"].push(path)
else acc["assets"].push(path)
return acc
},
{ pages: [], components: [], assets: [] } as Record<string, string[]>
)
log("Building the pages")
const server = await Bun.build({
target: "bun",
entrypoints: entries["pages"],
external: ["react", "react-dom"],
outdir: resolve("build", "app"),
plugins: [
{
name: "rsc-register",
setup(build) {
build.onLoad({ filter: /\.tsx?$/ }, async args => {
const content = await Bun.file(args.path).text()
const { exports } = new Bun.Transpiler({ loader: "tsx" }).scan(content)
if (exports.length === 0) return { contents: content } // If there are no exports, we let it be bundled
// We want to categorize the only the pages
if (args.path.endsWith("page.tsx"))
if (exports.some(e => e === "dynamic")) meta.pages.dynamic.push(args.path.split("/").at(-2)!)
else meta.pages.static.push(args.path.split("/").at(-2)!) // We fallback to static
const directives = content.match(/(?:^|\n|;)"use (client|server)";?/)
if (!directives) return { contents: content } // If there are no directives, we also let it be bundled
return {
contents: exports.map(e => createReference(e, args.path, directives[1])).join("\n")
}
})
}
}
]
})
log("Successful build?".dim, server.success)
if (!server.success) {
log(server)
process.exit(1)
}
log("Building the components")
const client = await Bun.build({
target: "bun",
external: ["react", "react-dom", "react-server-dom-esm"],
entrypoints: entries["components"],
root: resolve("src"),
outdir: resolve("build")
})
log("Successful build?".dim, client.success)
if (!client.success) {
log(client)
process.exit(1)
}
entries["assets"].forEach(asset => Bun.write(asset.replace("src", "build"), Bun.file(asset)))
log("Done! 🎉".bold)
// Write the meta file
Bun.write(resolve("build", "meta.json"), JSON.stringify(meta))