diff --git a/cshare-app/scripts/precompress.mjs b/cshare-app/scripts/precompress.mjs new file mode 100644 index 0000000..d33b035 --- /dev/null +++ b/cshare-app/scripts/precompress.mjs @@ -0,0 +1,54 @@ +import fs from 'node:fs/promises'; +import path from 'node:path'; +import { brotliCompress, constants, gzip } from 'node:zlib'; +import { promisify } from 'node:util'; + +const gzipAsync = promisify(gzip); +const brotliAsync = promisify(brotliCompress); +const distDir = path.resolve('dist'); +const extensions = new Set([ + '.css', + '.html', + '.js', + '.json', + '.svg', + '.txt', + '.ttf', +]); + +async function walk(dir) { + const entries = await fs.readdir(dir, { withFileTypes: true }); + const files = await Promise.all(entries.map(async (entry) => { + const fullPath = path.join(dir, entry.name); + if (entry.isDirectory()) return walk(fullPath); + return fullPath; + })); + return files.flat(); +} + +async function compressFile(filePath) { + if (!extensions.has(path.extname(filePath))) return; + + const input = await fs.readFile(filePath); + if (input.length < 1024) return; + + const [gz, br] = await Promise.all([ + gzipAsync(input, { level: 9 }), + brotliAsync(input, { + params: { + [constants.BROTLI_PARAM_QUALITY]: 11, + }, + }), + ]); + + await Promise.all([ + fs.writeFile(`${filePath}.gz`, gz), + fs.writeFile(`${filePath}.br`, br), + ]); +} + +const files = await walk(distDir); +await Promise.all(files.map(compressFile)); + +console.log(`Precompressed ${files.length} dist files with gzip and Brotli where beneficial.`); +