134 lines
4.0 KiB
JavaScript
134 lines
4.0 KiB
JavaScript
import { execFileSync } from "child_process";
|
|
import * as chokidar from "chokidar";
|
|
import esbuild from "esbuild";
|
|
import fs from "fs";
|
|
import { globSync } from "glob";
|
|
import path from "path";
|
|
import { cwd } from "process";
|
|
import process from "process";
|
|
import { fileURLToPath } from "url";
|
|
|
|
// Hack replaces what was lost when using Bun / later Node versions
|
|
const __dirname = fileURLToPath(new URL(".", import.meta.url));
|
|
|
|
const isProdBuild = process.env.NODE_ENV === "production";
|
|
|
|
const definitions = {
|
|
"process.env.NODE_ENV": JSON.stringify(isProdBuild ? "production" : "development"),
|
|
"process.env.CWD": JSON.stringify(cwd()),
|
|
};
|
|
|
|
// If you have assets in your src folder that won't be built/bundled, put them into "otherFiles" to
|
|
// copy them. All this is a replacement for rollup-copy-plugin, which I used to use.
|
|
|
|
const otherFiles = [
|
|
["./src/*.css", "."],
|
|
["./src/*.png", "."]
|
|
];
|
|
|
|
const isFile = (filePath) => fs.statSync(filePath).isFile();
|
|
function nameCopyTarget(src, dest, strip) {
|
|
const target = path.join(dest, strip ? src.replace(strip, "") : path.parse(src).base);
|
|
return [src, target];
|
|
}
|
|
|
|
function copyOthers() {
|
|
for (const [source, rawdest, strip] of otherFiles) {
|
|
const matchedPaths = globSync(source);
|
|
const dest = path.join("dist", rawdest);
|
|
const copyTargets = matchedPaths.map((path) => nameCopyTarget(path, dest, strip));
|
|
for (const [src, dest] of copyTargets) {
|
|
if (isFile(src)) {
|
|
fs.mkdirSync(path.dirname(dest), { recursive: true });
|
|
fs.copyFileSync(src, dest);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// This starts the definitions used for esbuild: Targets, arguments, the function for running a
|
|
// build, and the options for building: building or watching. If you're building more than one app,
|
|
// order them by the approximately largest project to smallest to build even faster.
|
|
|
|
const apps = [
|
|
["index.ts", "."]
|
|
];
|
|
|
|
const baseArgs = {
|
|
bundle: true,
|
|
write: true,
|
|
sourcemap: true,
|
|
minify: isProdBuild,
|
|
splitting: true,
|
|
treeShaking: true,
|
|
external: ["*.woff", "*.woff2"],
|
|
tsconfig: "./tsconfig.json",
|
|
loader: { ".css": "text", ".md": "text" },
|
|
define: definitions,
|
|
format: "esm",
|
|
};
|
|
|
|
async function buildOneSource(source, dest) {
|
|
const DIST = path.join(__dirname, "./dist", dest);
|
|
console.log(`[${new Date(Date.now()).toISOString()}] Starting build for target ${source}`);
|
|
|
|
try {
|
|
const start = Date.now();
|
|
copyOthers();
|
|
await esbuild.build({
|
|
...baseArgs,
|
|
entryPoints: [`./src/${source}`],
|
|
entryNames: '[dir]/[name]',
|
|
outdir: DIST,
|
|
});
|
|
const end = Date.now();
|
|
console.log(
|
|
`[${new Date(end).toISOString()}] Finished build for target ${source} in ${
|
|
Date.now() - start
|
|
}ms`,
|
|
);
|
|
} catch (exc) {
|
|
console.error(`[${new Date(Date.now()).toISOString()}] Failed to build ${source}: ${exc}`);
|
|
}
|
|
}
|
|
|
|
async function buildAll(apps) {
|
|
await Promise.allSettled(apps.map(([source, dest]) => buildOneSource(source, dest)));
|
|
}
|
|
|
|
let timeoutId = null;
|
|
function debouncedBuild() {
|
|
if (timeoutId !== null) {
|
|
clearTimeout(timeoutId);
|
|
}
|
|
timeoutId = setTimeout(() => {
|
|
console.log("\x1bc");
|
|
buildAll(apps);
|
|
}, 250);
|
|
}
|
|
|
|
if (process.argv.length > 2 && (process.argv[2] === "-h" || process.argv[2] === "--help")) {
|
|
console.log(`Build:
|
|
|
|
options:
|
|
-w, --watch: Build all ${apps.length} applications
|
|
-h, --help: This help message
|
|
`);
|
|
process.exit(0);
|
|
}
|
|
|
|
if (process.argv.length > 2 && (process.argv[2] === "-w" || process.argv[2] === "--watch")) {
|
|
console.log("Watching ./src for changes");
|
|
chokidar.watch("./src").on("all", (event, path) => {
|
|
if (!["add", "change", "unlink"].includes(event)) {
|
|
return;
|
|
}
|
|
if (!/(\.css|\.ts|\.js)$/.test(path)) {
|
|
return;
|
|
}
|
|
debouncedBuild();
|
|
});
|
|
} else {
|
|
await buildAll(apps);
|
|
}
|