Personal Website, vers. 1 (pushed far to late)
This commit is contained in:
commit
c8df66d3da
103 files changed
+8977
No files matched your search
@@ -0,0 +1,45 @@
|
||||
import * as esbuild from 'esbuild';
|
||||
import { mkdir, rm, writeFile } from 'node:fs/promises';
|
||||
import path from 'node:path';
|
||||
|
||||
export const outdir = 'dist/assets';
|
||||
|
||||
export function buildOptions({ dev = false } = {}) {
|
||||
return {
|
||||
entryPoints: [
|
||||
{ in: 'client/js/main.js', out: 'app' },
|
||||
{ in: 'client/css/main.css', out: 'app' },
|
||||
],
|
||||
outdir,
|
||||
bundle: true,
|
||||
format: 'esm',
|
||||
minify: !dev,
|
||||
sourcemap: dev ? 'linked' : false,
|
||||
metafile: true,
|
||||
entryNames: '[name]-[hash]',
|
||||
assetNames: '[name]-[hash]',
|
||||
loader: { '.woff2': 'file', '.woff': 'file' },
|
||||
// Old enough that esbuild lowers CSS nesting for Safari 15/16
|
||||
target: ['chrome109', 'firefox115', 'safari15.4'],
|
||||
logLevel: 'info',
|
||||
};
|
||||
}
|
||||
|
||||
// Maps "app.js" -> "/assets/app-HASH.js" so templates don't need to know the hash.
|
||||
export async function writeManifest(metafile) {
|
||||
const manifest = {};
|
||||
for (const [file, output] of Object.entries(metafile.outputs)) {
|
||||
if (!output.entryPoint) continue;
|
||||
const base = path.basename(file);
|
||||
const key = base.replace(/-[A-Z0-9]{8}(\.\w+)$/, '$1');
|
||||
manifest[key] = '/assets/' + base;
|
||||
}
|
||||
await writeFile('dist/manifest.json', JSON.stringify(manifest, null, 2));
|
||||
}
|
||||
|
||||
if (import.meta.url === `file://${process.argv[1]}`) {
|
||||
await rm('dist', { recursive: true, force: true });
|
||||
await mkdir(outdir, { recursive: true });
|
||||
const result = await esbuild.build(buildOptions());
|
||||
await writeManifest(result.metafile);
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
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);
|
||||
Reference in new issue
Block a user