feat: enforce frontend quality guardrails

This commit is contained in:
2026-08-24 13:07:14 +03:00
parent 826936c6a4
commit 1fc269adec
18 changed files with 542 additions and 42 deletions
+85
View File
@@ -0,0 +1,85 @@
import assert from "node:assert/strict";
import test from "node:test";
import {
assertBundleBudget,
getInitialAssetFiles,
getLazyRouteAssetSizes,
INITIAL_BUNDLE_BUDGET_BYTES,
measureAssets,
} from "./bundle-budget.mjs";
const manifest = {
"index.html": {
file: "assets/entry.js",
isEntry: true,
imports: ["_shared"],
dynamicImports: ["src/pages/account/ui/AccountPage.tsx"],
},
_shared: { file: "assets/shared.js", imports: ["_runtime"] },
_runtime: { file: "assets/runtime.js" },
"src/pages/account/ui/AccountPage.tsx": {
file: "assets/account.js",
isDynamicEntry: true,
src: "src/pages/account/ui/AccountPage.tsx",
},
"src/app/routes/ProtectedLayout.tsx": {
file: "assets/protected-layout.js",
isDynamicEntry: true,
src: "src/app/routes/ProtectedLayout.tsx",
},
};
const sizes = new Map([
["assets/entry.js", 200 * 1024],
["assets/shared.js", 175 * 1024],
["assets/runtime.js", 100 * 1024],
["assets/account.js", 250 * 1024],
["assets/protected-layout.js", 50 * 1024],
]);
test("measures only the eager import graph of the entry bundle", () => {
const assets = getInitialAssetFiles(manifest);
assert.deepEqual(assets, [
"assets/entry.js",
"assets/shared.js",
"assets/runtime.js",
]);
assert.equal(
measureAssets(assets, (asset) => sizes.get(asset)),
475 * 1024,
);
});
test("rejects an initial bundle above the configured budget", () => {
assert.throws(
() => assertBundleBudget(INITIAL_BUNDLE_BUDGET_BYTES + 1),
/JavaScript payload/,
);
});
test("rejects malformed manifests and lazy-route size regressions", () => {
assert.throws(() => getInitialAssetFiles({}), /entry/);
assert.deepEqual(
getLazyRouteAssetSizes(manifest, (asset) => sizes.get(asset)),
{
"src/app/routes/ProtectedLayout.tsx": 50 * 1024,
"src/pages/account/ui/AccountPage.tsx": 250 * 1024,
},
);
assert.throws(
() =>
getLazyRouteAssetSizes(manifest, (asset) => sizes.get(asset), {
"src/app/routes/ProtectedLayout.tsx": 50 * 1024,
"src/pages/account/ui/AccountPage.tsx": 249 * 1024,
}),
/route chunk/,
);
assert.throws(
() =>
getLazyRouteAssetSizes(manifest, (asset) => sizes.get(asset), {
"src/pages/account/ui/AccountPage.tsx": 250 * 1024,
}),
/Missing baseline/,
);
});