Files
Personal-Website/scripts/dev.js
T

63 lines
1.7 KiB
JavaScript

import * as esbuild from 'esbuild';
import { spawn } from 'node:child_process';
import { existsSync, watch } from 'node:fs';
import { mkdir, rm } from 'node:fs/promises';
import { buildOptions, outdir, writeManifest } from './build.js';
await rm('dist', { recursive: true, force: true });
await mkdir(outdir, { recursive: true });
const ctx = await esbuild.context({
...buildOptions({ dev: true }),
plugins: [
{
name: 'manifest',
setup(build) {
build.onEnd((result) => result.metafile && writeManifest(result.metafile));
},
},
],
});
await ctx.watch();
// Restarting the server ourselves instead of node --watch-path: on Node 24 the
// watch-mode parent sometimes crashes on shutdown and leaves the server running.
const args = [...(existsSync('.env') ? ['--env-file=.env'] : []), 'src/server.js'];
let server;
function start() {
server = spawn(process.execPath, args, { stdio: 'inherit', env: { ...process.env, NODE_ENV: 'development' } });
}
function restart() {
if (!server || server.exitCode !== null) return start();
server.once('exit', start);
server.kill();
}
let timer;
for (const dir of ['src', 'locales']) {
watch(dir, { recursive: true }, (event, file) => {
if (file?.endsWith('.njk')) return; // templates are re-read on every request anyway
clearTimeout(timer);
timer = setTimeout(() => {
console.log(`[dev] ${dir}/${file} changed, restarting`);
restart();
}, 150);
});
}
start();
async function stop() {
await ctx.dispose();
if (server?.exitCode === null) {
server.once('exit', () => process.exit(0));
server.kill();
} else {
process.exit(0);
}
}
process.on('SIGINT', stop);
process.on('SIGTERM', stop);