// Lays a .br and a .gz beside every compressible file of the editor's // bundle, once, when the image is built (precompressMain.ts); F sends them // instead of the file (editorFiles.ts). At the strongest level (brotli's is // its default), because it costs only the build: the editor's bundle shrinks to about a third, and a // tablet on the school's network feels that at every opening. A packed file // that is not smaller is not laid. import { readdir, readFile, writeFile } from 'node:fs/promises'; import { extname, join } from 'node:path'; import { promisify } from 'node:util'; import { brotliCompress, constants, gzip } from 'node:zlib'; export const COMPRESSIBLE = new Set(['.html', '.js', '.mjs', '.css', '.json', '.svg', '.txt']); const packers = [ { suffix: '.br', pack: (bytes: Buffer) => promisify(brotliCompress)(bytes) }, { suffix: '.gz', pack: (bytes: Buffer) => promisify(gzip)(bytes, { level: constants.Z_BEST_COMPRESSION }) }, ]; /** Packs the compressible files under `folder`; returns how many packed files it laid. */ export async function precompress(folder: string): Promise { let laid = 0; for (const entry of await readdir(folder, { withFileTypes: true })) { const path = join(folder, entry.name); if (entry.isDirectory()) laid += await precompress(path); else if (entry.isFile() && COMPRESSIBLE.has(extname(entry.name))) { const bytes = await readFile(path); for (const { suffix, pack } of packers) { const packed = await pack(bytes); if (packed.length >= bytes.length) continue; await writeFile(path + suffix, packed); laid += 1; } } } return laid; }