ci: establish trusted quality baseline
This commit is contained in:
@@ -14,6 +14,14 @@ const outputPath = resolve(
|
||||
const routes = parseList(
|
||||
process.env.PERF_ROUTES ?? "/splash,/chat,/subscription,/tip",
|
||||
);
|
||||
const enforceBudgets = process.env.PERF_BUNDLE_ENFORCE === "1";
|
||||
|
||||
const eagerClientJsBudgets = new Map([
|
||||
["/splash", 650 * 1024],
|
||||
["/chat", 675 * 1024],
|
||||
["/subscription", 665 * 1024],
|
||||
["/tip", 660 * 1024],
|
||||
]);
|
||||
|
||||
const auditTargets = [
|
||||
{
|
||||
@@ -46,6 +54,19 @@ function main() {
|
||||
const routeReports = routes.map((route) =>
|
||||
analyzeRoute(route, asyncBoundariesByPath),
|
||||
);
|
||||
const budgetResults = routeReports.flatMap((route) => {
|
||||
const budgetBytes = eagerClientJsBudgets.get(route.route);
|
||||
if (budgetBytes === undefined) return [];
|
||||
|
||||
return [
|
||||
{
|
||||
route: route.route,
|
||||
budgetBytes,
|
||||
actualBytes: route.eagerClientJs.compressedBytes,
|
||||
withinBudget: route.eagerClientJs.compressedBytes <= budgetBytes,
|
||||
},
|
||||
];
|
||||
});
|
||||
const packageJson = JSON.parse(
|
||||
readFileSync(resolve(root, "package.json"), "utf8"),
|
||||
);
|
||||
@@ -54,6 +75,7 @@ function main() {
|
||||
generatedAt: new Date().toISOString(),
|
||||
nextVersion: packageJson.dependencies.next,
|
||||
routes: routeReports,
|
||||
eagerClientJsBudgets: budgetResults,
|
||||
};
|
||||
|
||||
mkdirSync(dirname(outputPath), { recursive: true });
|
||||
@@ -65,6 +87,7 @@ function main() {
|
||||
"eager client JS": formatBytes(route.eagerClientJs.compressedBytes),
|
||||
"async client JS": formatBytes(route.asyncClientJs.compressedBytes),
|
||||
"total client JS": formatBytes(route.totalClientJs.compressedBytes),
|
||||
budget: formatBudget(route, budgetResults),
|
||||
})),
|
||||
);
|
||||
|
||||
@@ -84,6 +107,22 @@ function main() {
|
||||
}
|
||||
|
||||
console.log(`\nBundle summary written to ${outputPath}`);
|
||||
|
||||
if (!enforceBudgets) return;
|
||||
|
||||
const failures = budgetResults.filter((result) => !result.withinBudget);
|
||||
if (failures.length === 0) {
|
||||
console.log("All eager client JS budgets passed.");
|
||||
return;
|
||||
}
|
||||
|
||||
console.error("\nEager client JS budget exceeded:");
|
||||
for (const failure of failures) {
|
||||
console.error(
|
||||
`- ${failure.route}: ${formatBytes(failure.actualBytes)} > ${formatBytes(failure.budgetBytes)}`,
|
||||
);
|
||||
}
|
||||
process.exitCode = 1;
|
||||
}
|
||||
|
||||
function analyzeRoute(route, boundariesByPath) {
|
||||
@@ -297,6 +336,12 @@ function formatBytes(bytes) {
|
||||
return `${(bytes / 1024).toFixed(1)} KiB`;
|
||||
}
|
||||
|
||||
function formatBudget(route, budgetResults) {
|
||||
const result = budgetResults.find((item) => item.route === route.route);
|
||||
if (result === undefined) return "not set";
|
||||
return `${result.withinBudget ? "pass" : "fail"} / ${formatBytes(result.budgetBytes)}`;
|
||||
}
|
||||
|
||||
class FramedDataFile {
|
||||
constructor(filePath) {
|
||||
this.buffer = readFileSync(filePath);
|
||||
|
||||
Reference in New Issue
Block a user