-
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathbuild.js
executable file
·140 lines (117 loc) · 4.75 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
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
#!/usr/bin/env node
import fs from 'node:fs';
import path from 'node:path';
import os from 'node:os';
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';
import { eslintPlugin } from './pkg/lib/esbuild-eslint-plugin.js';
import { stylelintPlugin } from './pkg/lib/esbuild-stylelint-plugin.js';
const production = process.env.NODE_ENV === 'production';
const useWasm = os.arch() !== 'x64';
const esbuild = (await import(useWasm ? 'esbuild-wasm' : 'esbuild')).default;
const lintDefault = process.env.LINT ? process.env.LINT === '0' : production;
const parser = (await import('argparse')).default.ArgumentParser();
parser.add_argument('-r', '--rsync', { help: "rsync bundles to ssh target after build", metavar: "HOST" });
parser.add_argument('-w', '--watch', { action: 'store_true', help: "Enable watch mode", default: process.env.ESBUILD_WATCH === "true" });
parser.add_argument('-e', '--no-eslint', { action: 'store_true', help: "Disable eslint linting", default: lintDefault });
parser.add_argument('-s', '--no-stylelint', { action: 'store_true', help: "Disable stylelint linting", default: lintDefault });
const args = parser.parse_args();
if (args.rsync)
process.env.RSYNC = args.rsync;
// 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.js'],
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: { ".js": "jsx" },
minify: production,
nodePaths,
outdir,
target: ['es2020'],
plugins: [
cleanPlugin(),
...args.no_stylelint ? [] : [stylelintPlugin({ filter: new RegExp(cwd + '\/src\/.*\.(css?|scss?)$') })],
...args.no_eslint ? [] : [eslintPlugin({ filter: new RegExp(cwd + '\/src\/.*\.(jsx?|js?)$') })],
// 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 (!args.watch)
process.exit(1);
// ignore errors in watch mode
}
if (args.watch) {
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();