Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
62 lines
2.0 KiB
JavaScript
62 lines
2.0 KiB
JavaScript
// Precompresses the built assets with brotli and drops the originals.
|
|
//
|
|
// The server used to brotli every static response on the fly, at the library's
|
|
// default quality, for every visitor. Compressing once at quality 11 is both
|
|
// smaller and free at request time. The uncompressed copies are removed rather
|
|
// than kept alongside, so the embedded FS (and the binary) shrinks instead of
|
|
// doubling; internal/web/index.go serves the `.br` sibling and inflates it for
|
|
// the rare client that does not send `Accept-Encoding: br`.
|
|
//
|
|
// index.html and .vite/manifest.json are left alone: Go reads and parses both.
|
|
import { constants, brotliCompressSync } from "node:zlib";
|
|
import { readdirSync, readFileSync, writeFileSync, unlinkSync, statSync } from "node:fs";
|
|
import { join, extname } from "node:path";
|
|
|
|
const DIST = "dist";
|
|
const COMPRESSIBLE = new Set([".js", ".css", ".svg", ".json", ".map"]);
|
|
const SKIP = new Set([join(DIST, "index.html"), join(DIST, ".vite", "manifest.json")]);
|
|
|
|
function* walk(dir) {
|
|
for (const entry of readdirSync(dir, { withFileTypes: true })) {
|
|
const path = join(dir, entry.name);
|
|
if (entry.isDirectory()) yield* walk(path);
|
|
else yield path;
|
|
}
|
|
}
|
|
|
|
let before = 0;
|
|
let after = 0;
|
|
let count = 0;
|
|
|
|
for (const file of walk(DIST)) {
|
|
const size = statSync(file).size;
|
|
before += size;
|
|
|
|
if (SKIP.has(file) || !COMPRESSIBLE.has(extname(file))) {
|
|
after += size;
|
|
continue;
|
|
}
|
|
|
|
const compressed = brotliCompressSync(readFileSync(file), {
|
|
params: {
|
|
[constants.BROTLI_PARAM_QUALITY]: constants.BROTLI_MAX_QUALITY,
|
|
[constants.BROTLI_PARAM_SIZE_HINT]: size,
|
|
},
|
|
});
|
|
|
|
// Brotli can lose on tiny files. Keeping the original also keeps the server's
|
|
// fast path honest, so only swap when it actually pays.
|
|
if (compressed.length >= size) {
|
|
after += size;
|
|
continue;
|
|
}
|
|
|
|
writeFileSync(`${file}.br`, compressed);
|
|
unlinkSync(file);
|
|
after += compressed.length;
|
|
count++;
|
|
}
|
|
|
|
const mb = (n) => (n / 1024 / 1024).toFixed(2);
|
|
console.log(`brotli: ${count} files, dist ${mb(before)} MB -> ${mb(after)} MB`);
|