import { readdir, readFile, writeFile } from "node:fs/promises"; import path from "node:path"; import { promisify } from "node:util"; import { fileURLToPath } from "node:url"; import { brotliCompress, constants, gzip } from "node:zlib"; const compressBrotli = promisify(brotliCompress); const compressGzip = promisify(gzip); const ELIGIBLE_EXTENSIONS = new Set([".css", ".js", ".json"]); const MINIMUM_BYTES = 1024; async function eligibleFiles(root) { const files = []; async function visit(directory) { const entries = await readdir(directory, { withFileTypes: true }); for (const entry of entries) { const filePath = path.join(directory, entry.name); if (entry.isDirectory()) await visit(filePath); else if (entry.isFile() && ELIGIBLE_EXTENSIONS.has(path.extname(entry.name).toLowerCase())) files.push(filePath); } } await visit(root); return files; } export async function precompressStatic(root) { const files = await eligibleFiles(root); let sourceBytes = 0; let brotliBytes = 0; let gzipBytes = 0; let writtenFiles = 0; for (const filePath of files) { const source = await readFile(filePath); if (source.length < MINIMUM_BYTES) continue; const [brotli, gzipped] = await Promise.all([ compressBrotli(source, { params: { [constants.BROTLI_PARAM_QUALITY]: 6 } }), compressGzip(source, { level: 9 }), ]); await Promise.all([ writeFile(`${filePath}.br`, brotli), writeFile(`${filePath}.gz`, gzipped), ]); sourceBytes += source.length; brotliBytes += brotli.length; gzipBytes += gzipped.length; writtenFiles += 2; } return { sourceFiles: writtenFiles / 2, writtenFiles, sourceBytes, brotliBytes, gzipBytes }; } if (process.argv[1] && path.resolve(process.argv[1]) === path.resolve(fileURLToPath(import.meta.url))) { const root = path.resolve(process.argv[2] ?? "dist"); const result = await precompressStatic(root); console.log(JSON.stringify({ root, ...result }, null, 2)); }