85 lines
2.4 KiB
TypeScript
85 lines
2.4 KiB
TypeScript
// This file implements client-side bundling, mostly wrapping esbuild.
|
|
const plugins: esbuild.Plugin[] = [
|
|
// There are currently no plugins needed by 'paperclover.net'
|
|
];
|
|
|
|
export async function bundleClientJavaScript(
|
|
referencedScripts: string[],
|
|
extraPublicScripts: string[],
|
|
incr: Incremental,
|
|
dev: boolean = false,
|
|
) {
|
|
const entryPoints = [
|
|
...new Set([
|
|
...referencedScripts,
|
|
...extraPublicScripts,
|
|
]),
|
|
];
|
|
if (entryPoints.length === 0) return;
|
|
const invalidFiles = entryPoints
|
|
.filter((file) => !file.match(/\.client\.[tj]sx?/));
|
|
if (invalidFiles.length > 0) {
|
|
const cwd = process.cwd();
|
|
throw new Error(
|
|
"All client-side scripts should be named like '.client.ts'. Exceptions: " +
|
|
invalidFiles.map((x) => path.join(cwd, x)).join(","),
|
|
);
|
|
}
|
|
|
|
const bundle = await esbuild.build({
|
|
bundle: true,
|
|
chunkNames: "/js/c.[hash]",
|
|
entryNames: "/js/[name]",
|
|
assetNames: "/asset/[hash]",
|
|
entryPoints,
|
|
format: "esm",
|
|
minify: !dev,
|
|
outdir: "/out!",
|
|
plugins,
|
|
splitting: true,
|
|
write: false,
|
|
});
|
|
if (bundle.errors.length || bundle.warnings.length) {
|
|
throw new AggregateError(
|
|
bundle.errors.concat(bundle.warnings),
|
|
"JS bundle failed",
|
|
);
|
|
}
|
|
incr.invalidate("bundle-script");
|
|
const publicScriptRoutes = extraPublicScripts.map((file) =>
|
|
path.basename(file).replace(/\.client\.[tj]sx?/, "")
|
|
);
|
|
const promises: Promise<unknown>[] = [];
|
|
// TODO: add a shared build hash to entrypoints, derived from all the chunk hashes.
|
|
for (const file of bundle.outputFiles) {
|
|
let route = file.path.replace(/^.*!/, "").replaceAll("\\", "/");
|
|
const text = file.text;
|
|
// Register non-chunks as script entries.
|
|
const chunk = route.startsWith("/js/c.");
|
|
if (!chunk) {
|
|
route = route.replace(".client.js", ".js");
|
|
incr.put({
|
|
srcId: "bundle-script",
|
|
type: "script",
|
|
key: route.slice("/js/".length, -".js".length),
|
|
value: text,
|
|
});
|
|
}
|
|
if (chunk || publicScriptRoutes.includes(route)) {
|
|
promises.push(incr.putAsset({
|
|
srcId: "bundle-script",
|
|
key: route,
|
|
body: text,
|
|
}));
|
|
}
|
|
}
|
|
|
|
if (promises.length > 0) {
|
|
await Promise.all(promises);
|
|
}
|
|
}
|
|
|
|
import * as esbuild from "esbuild";
|
|
import * as path from "node:path";
|
|
import process from "node:process";
|
|
import { Incremental } from "./incremental.ts";
|