-
Notifications
You must be signed in to change notification settings - Fork 9
/
build.js
executable file
·125 lines (104 loc) · 3.27 KB
/
build.js
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
112
113
114
115
116
117
118
119
120
121
122
123
124
125
#!/usr/bin/env node
import fs from "node:fs";
import path from "node:path";
import copy from "esbuild-plugin-copy";
import { cleanPlugin } from "./pkg/lib/esbuild-cleanup-plugin.js";
import { cockpitCompressPlugin } from "./pkg/lib/esbuild-compress-plugin.js";
import { cockpitPoEsbuildPlugin } from "./pkg/lib/cockpit-po-plugin.js";
import { cockpitRsyncEsbuildPlugin } from "./pkg/lib/cockpit-rsync-plugin.js";
import { esbuildStylesPlugins } from "./pkg/lib/esbuild-common.js";
const esbuild = (await import("esbuild")).default;
const production = process.env.NODE_ENV === "production";
const watchMode = process.env.ESBUILD_WATCH === "true";
// List of directories to use when using import statements
const nodePaths = ["pkg/lib"];
const outdir = "dist";
// Obtain package name from package.json
const packageJson = JSON.parse(fs.readFileSync("package.json"));
function notifyEndPlugin() {
return {
name: "notify-end",
setup(build) {
let startTime;
build.onStart(() => {
startTime = new Date();
});
build.onEnd(() => {
const endTime = new Date();
const timeStamp = endTime.toTimeString().split(" ")[0];
console.log(
`${timeStamp}: Build finished in ${endTime - startTime} ms`,
);
});
},
};
}
const cwd = process.cwd();
// similar to fs.watch(), but recursively watches all subdirectories
function watch_dirs(dir, on_change) {
const callback = (ev, dir, fname) => {
// only listen for "change" events, as renames are noisy
// ignore hidden files
const isHidden = /^\./.test(fname);
if (ev !== "change" || isHidden) {
return;
}
on_change(path.join(dir, fname));
};
fs.watch(dir, {}, (ev, path) => callback(ev, dir, path));
// watch all subdirectories in dir
const d = fs.opendirSync(dir);
let dirent;
while ((dirent = d.readSync()) !== null) {
if (dirent.isDirectory())
watch_dirs(path.join(dir, dirent.name), on_change);
}
d.closeSync();
}
const context = await esbuild.context({
...(!production ? { sourcemap: "linked" } : {}),
bundle: true,
entryPoints: ["./src/index.ts"],
external: ["*.woff", "*.woff2", "*.jpg", "*.svg", "../../assets*"], // Allow external font files which live in ../../static/fonts
legalComments: "external", // Move all legal comments to a .LEGAL.txt file
loader: { ".ts": "tsx" },
minify: production,
nodePaths,
outdir,
target: ["es2020"],
plugins: [
cleanPlugin(),
// Esbuild will only copy assets that are explicitly imported and used
// in the code. This is a problem for index.html and manifest.json which are not imported
copy({
assets: [
{ from: ["./src/manifest.json"], to: ["./manifest.json"] },
{ from: ["./src/index.html"], to: ["./index.html"] },
],
}),
...esbuildStylesPlugins,
cockpitPoEsbuildPlugin(),
...(production ? [cockpitCompressPlugin()] : []),
cockpitRsyncEsbuildPlugin({ dest: packageJson.name }),
notifyEndPlugin(),
],
});
try {
await context.rebuild();
} catch (e) {
if (!watchMode) process.exit(1);
// ignore errors in watch mode
}
if (watchMode) {
const on_change = async (path) => {
console.log("change detected:", path);
await context.cancel();
try {
await context.rebuild();
} catch (e) {} // ignore in watch mode
};
watch_dirs("src", on_change);
// wait forever until Control-C
await new Promise(() => {});
}
context.dispose();