Files
bentopdf/scripts/compress-static-assets.mjs
T

75 lines
2.2 KiB
JavaScript

import fs from 'fs';
import os from 'os';
import path from 'path';
import zlib from 'zlib';
import { promisify } from 'util';
import { fileURLToPath } from 'url';
const __dirname = path.dirname(fileURLToPath(import.meta.url));
const DIST_DIR = path.resolve(__dirname, '../dist');
const COMPRESSIBLE = /\.(html|js|mjs|css|json|svg|wasm|xml|txt|webmanifest)$/i;
const MIN_SIZE = 1024;
const MODES = { o: [], g: ['.gz'], b: ['.br'], all: ['.gz', '.br'] };
const brotli = promisify(zlib.brotliCompress);
const gzip = promisify(zlib.gzip);
const ENCODERS = {
'.gz': (data) => gzip(data, { level: 9 }),
'.br': (data) =>
brotli(data, {
params: { [zlib.constants.BROTLI_PARAM_QUALITY]: 11 },
}),
};
const mode = process.env.COMPRESSION_MODE || 'o';
if (!MODES[mode]) {
console.error(
`Invalid COMPRESSION_MODE "${mode}". Use o (none), g (.gz), b (.br) or all (.gz and .br).`
);
process.exit(1);
}
function listFiles(dir) {
return fs.readdirSync(dir, { withFileTypes: true }).flatMap((entry) => {
const full = path.join(dir, entry.name);
if (entry.isDirectory()) return listFiles(full);
return entry.isFile() ? [full] : [];
});
}
const queue = MODES[mode].length
? listFiles(DIST_DIR).filter(
(file) => COMPRESSIBLE.test(file) && fs.statSync(file).size >= MIN_SIZE
)
: [];
let written = 0;
async function compress(file) {
const { mtimeMs } = fs.statSync(file);
const stale = MODES[mode].filter((ext) => {
const copy = `${file}${ext}`;
return !fs.existsSync(copy) || fs.statSync(copy).mtimeMs < mtimeMs;
});
if (!stale.length) return;
const data = await fs.promises.readFile(file);
for (const ext of stale) {
const encoded = await ENCODERS[ext](data);
if (encoded.length < data.length) {
await fs.promises.writeFile(`${file}${ext}`, encoded);
written++;
} else {
fs.rmSync(`${file}${ext}`, { force: true });
}
}
}
async function worker() {
for (let file = queue.pop(); file; file = queue.pop()) {
await compress(file);
}
}
await Promise.all(Array.from({ length: os.availableParallelism() }, worker));
console.log(`Compression mode ${mode}: wrote ${written} precompressed files.`);