39 lines
1.4 KiB
JavaScript
39 lines
1.4 KiB
JavaScript
|
|
import { readdir, readFile, stat, utimes, writeFile } from "node:fs/promises";
|
||
|
|
import { gzip } from "node:zlib";
|
||
|
|
import { promisify } from "node:util";
|
||
|
|
|
||
|
|
const gzipAsync = promisify(gzip);
|
||
|
|
const assetDirectory = new URL("../dist/assets/", import.meta.url);
|
||
|
|
const compressedExtensions = /\.(?:js|css|json|svg)$/i;
|
||
|
|
const minimumBytes = 1024;
|
||
|
|
let compressedCount = 0;
|
||
|
|
let sourceBytes = 0;
|
||
|
|
let gzipBytes = 0;
|
||
|
|
|
||
|
|
async function compressAssets(directory) {
|
||
|
|
for (const entry of await readdir(directory, { withFileTypes: true })) {
|
||
|
|
const path = new URL(`${entry.name}${entry.isDirectory() ? "/" : ""}`, directory);
|
||
|
|
if (entry.isDirectory()) {
|
||
|
|
await compressAssets(path);
|
||
|
|
continue;
|
||
|
|
}
|
||
|
|
if (!compressedExtensions.test(entry.name)) continue;
|
||
|
|
|
||
|
|
const info = await stat(path);
|
||
|
|
if (info.size < minimumBytes) continue;
|
||
|
|
const source = await readFile(path);
|
||
|
|
const compressed = await gzipAsync(source, { level: 9 });
|
||
|
|
const compressedPath = new URL(`${entry.name}.gz`, directory);
|
||
|
|
await writeFile(compressedPath, compressed);
|
||
|
|
// Nginx gzip_static can safely pair the sidecar with its source file.
|
||
|
|
await utimes(compressedPath, info.atime, info.mtime);
|
||
|
|
compressedCount += 1;
|
||
|
|
sourceBytes += source.byteLength;
|
||
|
|
gzipBytes += compressed.byteLength;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
await compressAssets(assetDirectory);
|
||
|
|
console.log(
|
||
|
|
`Precompressed ${compressedCount} assets: ${sourceBytes} -> ${gzipBytes} bytes`,
|
||
|
|
);
|