Files
ukmesh/frontend/scripts/check-performance-budgets.mjs
T

73 lines
2.2 KiB
JavaScript

import { gzipSync } from 'node:zlib';
import { readdir, readFile } from 'node:fs/promises';
import path from 'node:path';
const KIB = 1024;
const outputDir = path.resolve('dist/assets');
const files = await readdir(outputDir);
async function measure(matcher) {
const selected = files.filter(matcher);
const buffers = await Promise.all(selected.map((file) => readFile(path.join(outputDir, file))));
return {
files: selected,
raw: buffers.reduce((total, buffer) => total + buffer.byteLength, 0),
gzip: buffers.reduce((total, buffer) => total + gzipSync(buffer).byteLength, 0),
};
}
const budgets = [
{
name: 'main App chunk',
measure: await measure((file) => /^App-[^.]+\.js$/.test(file)),
raw: 900 * KIB,
gzip: 260 * KIB,
exactlyOne: true,
},
{
name: 'MapLibre chunk',
measure: await measure((file) => /^maplibre-gl-[^.]+\.js$/.test(file)),
raw: 820 * KIB,
gzip: 225 * KIB,
exactlyOne: true,
},
{
name: 'Recharts categorical chunk',
measure: await measure((file) => /^generateCategoricalChart-[^.]+\.js$/.test(file)),
raw: 400 * KIB,
gzip: 110 * KIB,
exactlyOne: true,
},
{
name: 'all JavaScript',
measure: await measure((file) => file.endsWith('.js')),
raw: 2_900 * KIB,
gzip: 850 * KIB,
},
{
name: 'all CSS',
measure: await measure((file) => file.endsWith('.css')),
raw: 230 * KIB,
gzip: 42 * KIB,
},
];
let failed = false;
for (const budget of budgets) {
const rawKib = budget.measure.raw / KIB;
const gzipKib = budget.measure.gzip / KIB;
const missing = budget.exactlyOne && budget.measure.files.length !== 1;
const exceeds = budget.measure.raw > budget.raw || budget.measure.gzip > budget.gzip;
const status = missing || exceeds ? 'FAIL' : 'PASS';
console.log(
`${status} ${budget.name}: ${rawKib.toFixed(1)} KiB raw / ${gzipKib.toFixed(1)} KiB gzip`
+ ` (limits ${(budget.raw / KIB).toFixed(0)} / ${(budget.gzip / KIB).toFixed(0)})`,
);
if (missing) {
console.error(`Expected exactly one matching asset, found: ${budget.measure.files.join(', ') || 'none'}`);
}
failed ||= missing || exceeds;
}
if (failed) process.exitCode = 1;