Files
makelore/scripts/check-performance-budget.mjs

57 lines
2.1 KiB
JavaScript

import { existsSync, readdirSync, readFileSync, statSync } from 'node:fs';
import { gzipSync } from 'node:zlib';
import { basename, join, resolve } from 'node:path';
const root = resolve(process.cwd());
const dist = resolve(root, 'dist');
const assets = join(dist, 'assets');
const budgets = {
initialJsGzip: 350 * 1024,
initialCssGzip: 30 * 1024,
fontsBytes: 2 * 1024 * 1024,
moduleMediaBytes: 1 * 1024 * 1024,
};
function readAsset(relativePath) {
return readFileSync(join(dist, relativePath));
}
function gzipBytes(bytes) {
return gzipSync(bytes, { level: 9 }).byteLength;
}
function formatBytes(bytes) {
return `${(bytes / 1024).toFixed(1)} KiB`;
}
if (!existsSync(join(dist, 'index.html')) || !existsSync(assets)) {
console.error('性能预算检查需要先运行 pnpm run build:vite。');
process.exit(1);
}
const html = readFileSync(join(dist, 'index.html'), 'utf8');
const initialJs = [...html.matchAll(/<script[^>]+src="\.\/([^\"]+\.js)"/g)]
.map((match) => match[1])
.reduce((total, relativePath) => total + gzipBytes(readAsset(relativePath)), 0);
const initialCss = [...html.matchAll(/<link[^>]+href="\.\/([^\"]+\.css)"/g)]
.map((match) => match[1])
.reduce((total, relativePath) => total + gzipBytes(readAsset(relativePath)), 0);
const assetNames = readdirSync(assets);
const fontBytes = assetNames
.filter((name) => /\.(woff2?|otf|ttf)$/i.test(name))
.reduce((total, name) => total + statSync(join(assets, name)).size, 0);
const moduleMediaBytes = assetNames
.filter((name) => /^module-.*\.(avif|webp|png|jpe?g)$/i.test(name))
.reduce((total, name) => total + statSync(join(assets, name)).size, 0);
const metrics = { initialJsGzip: initialJs, initialCssGzip: initialCss, fontsBytes: fontBytes, moduleMediaBytes };
console.log(JSON.stringify({ metrics, budgets }, null, 2));
const failures = Object.entries(budgets)
.filter(([key, budget]) => metrics[key] > budget)
.map(([key, budget]) => `${key} ${formatBytes(metrics[key])} > ${formatBytes(budget)}`);
if (failures.length > 0) {
console.error(`性能预算超标:${failures.join('; ')}`);
process.exit(1);
}