73 lines
2.0 KiB
JavaScript
73 lines
2.0 KiB
JavaScript
#!/usr/bin/env node
|
|||
|
|
|
||
|
|
import fs from "node:fs";
|
||
|
|
import path from "node:path";
|
||
|
|
import zlib from "node:zlib";
|
||
|
|
|
||
|
|
const BUDGET_KB = 550;
|
||
|
|
|
||
|
|
const DIST = path.join(process.cwd(), "dist");
|
||
|
|
const reportOnly = process.argv.includes("--report");
|
||
|
|
|
||
|
|
if (!fs.existsSync(DIST)) {
|
||
|
|
console.error("No dist/ — run `npm run build` first.");
|
||
|
|
process.exit(1);
|
||
|
|
}
|
||
|
|
|
||
|
|
const html = fs.readFileSync(path.join(DIST, "index.html"), "utf8");
|
||
|
|
|
||
|
|
const assets = [
|
||
|
|
...html.matchAll(/(?:src|href)="\/?(assets\/[^"]+\.(?:js|css))"/g),
|
||
|
|
].map((match) => match[1]);
|
||
|
|
|
||
|
|
if (assets.length === 0) {
|
||
|
|
console.error("Found no assets in dist/index.html — has the build changed?");
|
||
|
|
process.exit(1);
|
||
|
|
}
|
||
|
|
|
||
|
|
let raw = 0;
|
||
|
|
let gzipped = 0;
|
||
|
|
const rows = [];
|
||
|
|
|
||
|
|
for (const asset of [...new Set(assets)]) {
|
||
|
|
const file = path.join(DIST, asset);
|
||
|
|
if (!fs.existsSync(file)) continue;
|
||
|
|
const contents = fs.readFileSync(file);
|
||
|
|
const gz = zlib.gzipSync(contents).length;
|
||
|
|
raw += contents.length;
|
||
|
|
gzipped += gz;
|
||
|
|
rows.push({ asset, kb: contents.length / 1024, gzipKb: gz / 1024 });
|
||
|
|
}
|
||
|
|
|
||
|
|
rows.sort((a, b) => b.kb - a.kb);
|
||
|
|
|
||
|
|
console.log("First paint:");
|
||
|
|
for (const row of rows) {
|
||
|
|
console.log(
|
||
|
|
` ${row.asset.padEnd(44)} ${row.kb.toFixed(1).padStart(8)} kB` +
|
||
|
|
` (gzip ${row.gzipKb.toFixed(1)} kB)`
|
||
|
|
);
|
||
|
|
}
|
||
|
|
|
||
|
|
const totalKb = raw / 1024;
|
||
|
|
console.log(
|
||
|
|
` ${"total".padEnd(44)} ${totalKb.toFixed(1).padStart(8)} kB` +
|
||
|
|
` (gzip ${(gzipped / 1024).toFixed(1)} kB)`
|
||
|
|
);
|
||
|
|
|
||
|
|
if (reportOnly) process.exit(0);
|
||
|
|
|
||
|
|
if (totalKb > BUDGET_KB) {
|
||
|
|
console.error(
|
||
|
|
`\nFirst paint is ${totalKb.toFixed(1)} kB, over the ${BUDGET_KB} kB budget.\n\n` +
|
||
|
|
"Something large has entered the initial payload. Usually that is a\n" +
|
||
|
|
"dependency imported by a shared component rather than by the screen that\n" +
|
||
|
|
"needs it — check the largest chunk above.\n\n" +
|
||
|
|
"If the growth is deliberate, raise BUDGET_KB in this file and say what\n" +
|
||
|
|
"grew, so the next person can tell a decision from a drift."
|
||
|
|
);
|
||
|
|
process.exit(1);
|
||
|
|
}
|
||
|
|
|
||
|
|
console.log(`\nWithin budget (${BUDGET_KB} kB).`);
|