-
Notifications
You must be signed in to change notification settings - Fork 676
/
Copy pathbundle.ts
104 lines (92 loc) · 2.95 KB
/
bundle.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
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
import { BUILD_ID } from "./constants.ts";
import { denoPlugin, esbuild, toFileUrl } from "./deps.ts";
import { Island } from "./types.ts";
let esbuildInitalized: boolean | Promise<void> = false;
async function ensureEsbuildInialized() {
if (esbuildInitalized === false) {
if (Deno.run === undefined) {
esbuildInitalized = esbuild.initialize({
wasmURL: "https://unpkg.com/esbuild-wasm@0.14.39/esbuild.wasm",
worker: false,
});
} else {
esbuild.initialize({});
}
await esbuildInitalized;
esbuildInitalized = true;
} else if (esbuildInitalized instanceof Promise) {
await esbuildInitalized;
}
}
export class Bundler {
#importMapURL: URL;
#islands: Island[];
#cache: Map<string, Uint8Array> | Promise<void> | undefined = undefined;
constructor(islands: Island[], importMapURL: URL) {
this.#islands = islands;
this.#importMapURL = importMapURL;
}
async bundle() {
const entryPoints: Record<string, string> = {
"main": new URL("../../src/runtime/main.ts", import.meta.url).href,
};
for (const island of this.#islands) {
entryPoints[`island-${island.id}`] = island.url;
}
const absWorkingDir = Deno.cwd();
await ensureEsbuildInialized();
const bundle = await esbuild.build({
bundle: true,
define: { __FRSH_BUILD_ID: `"${BUILD_ID}"` },
entryPoints,
format: "esm",
metafile: true,
minify: true,
outdir: ".",
// This is requried to ensure the format of the outputFiles path is the same
// between windows and linux
absWorkingDir,
outfile: "",
platform: "neutral",
plugins: [denoPlugin({ importMapURL: this.#importMapURL })],
splitting: true,
target: ["chrome99", "firefox99", "safari15"],
treeShaking: true,
write: false,
});
// const metafileOutputs = bundle.metafile!.outputs;
// for (const path in metafileOutputs) {
// const meta = metafileOutputs[path];
// const imports = meta.imports
// .filter(({ kind }) => kind === "import-statement")
// .map(({ path }) => `/${path}`);
// this.#preloads.set(`/${path}`, imports);
// }
const cache = new Map<string, Uint8Array>();
const absDirUrlLength = toFileUrl(absWorkingDir).href.length;
for (const file of bundle.outputFiles) {
cache.set(
toFileUrl(file.path).href.substring(absDirUrlLength),
file.contents,
);
}
this.#cache = cache;
return;
}
async cache(): Promise<Map<string, Uint8Array>> {
if (this.#cache === undefined) {
this.#cache = this.bundle();
}
if (this.#cache instanceof Promise) {
await this.#cache;
}
return this.#cache as Map<string, Uint8Array>;
}
async get(path: string): Promise<Uint8Array | null> {
const cache = await this.cache();
return cache.get(path) ?? null;
}
// getPreloads(path: string): string[] {
// return this.#preloads.get(path) ?? [];
// }
}