mirror of
https://github.com/shankar0123/certctl.git
synced 2026-06-07 16:01:30 +00:00
5c5bbedc7e
Acquisition-audit SCALE-007 closure (Sprint 6 ACQ, 2026-05-16).
The web/src codebase has ~45 React.lazy() call sites (`grep -rE
'lazy\(' web/src --include='*.tsx' | wc -l`), heavily route-
splitting the SPA. Pre-2026-05-16 there was no CI guard on bundle
size, so unintended bloat in a vendor chunk or a page chunk would
slip in unnoticed until somebody profiled cold-start performance.
This commit adds:
- web/.size-limit.json — 11 budget entries: per-chunk caps on the
load-bearing chunks (main entry, vendor-recharts, vendor-react,
vendor-query, vendor-router, vendor-icons, OnboardingWizard,
CommandPalette, Timestamp) + two roll-up tiers (total vendor JS,
total app JS). Budgets tuned to current vite-build output +
~15% headroom in brotli-compressed bytes (the size-limit
default measurement mode — closest analogue to what a real
browser downloads).
- web/package.json + web/package-lock.json: `npm run size` script
+ size-limit + @size-limit/file devDeps.
- .github/workflows/ci.yml: new "Frontend bundle-size budget
(size-limit)" step in the frontend-build job, runs immediately
after the vite build.
- scripts/ci-guards/G-frontend-bundle-budget.sh: local-runnable
wrapper matching the existing ci-guards/<id>.sh contract — exits
0 on clean, non-zero with ::error:: prefix on regression.
Acceptance verified locally:
- npm install in web/ regenerates package-lock cleanly
- `npm run size` exits 0 against the committed web/dist/
- `bash scripts/ci-guards/G-frontend-bundle-budget.sh` exits 0
- All current chunks measured (brotli, kB): main entry 23.3
(cap 30), vendor-recharts 91.2 (cap 110), vendor-react 37.4
(cap 45), OnboardingWizard 28.6 (cap 35), total vendor 149.5
(cap 180), total app 351.1 (cap 425)
A regression that bloats a chunk past its cap fails CI and forces
an explicit operator decision: fix the regression, or raise the
cap in web/.size-limit.json with a rationale comment in the
commit message. Do not raise caps blindly.
65 lines
1.8 KiB
JSON
65 lines
1.8 KiB
JSON
{
|
|
"name": "certctl-dashboard",
|
|
"version": "1.0.0",
|
|
"private": true,
|
|
"type": "module",
|
|
"scripts": {
|
|
"dev": "vite",
|
|
"build": "tsc && vite build",
|
|
"preview": "vite preview",
|
|
"test": "vitest run",
|
|
"test:watch": "vitest",
|
|
"e2e": "playwright test",
|
|
"e2e:install": "playwright install --with-deps chromium",
|
|
"generate": "orval --config ./orval.config.ts",
|
|
"storybook": "storybook dev -p 6006",
|
|
"storybook:build": "storybook build --output-dir=.storybook-static",
|
|
"size": "size-limit"
|
|
},
|
|
"dependencies": {
|
|
"@floating-ui/react": "^0.27.19",
|
|
"@fontsource-variable/inter": "^5.2.8",
|
|
"@fontsource/jetbrains-mono": "^5.2.8",
|
|
"@headlessui/react": "^2.2.10",
|
|
"@hookform/resolvers": "^5.2.2",
|
|
"@tanstack/react-query": "^5.90.21",
|
|
"cmdk": "^1.1.1",
|
|
"lucide-react": "^1.16.0",
|
|
"react": "^18.3.1",
|
|
"react-dom": "^18.3.1",
|
|
"react-hook-form": "^7.75.0",
|
|
"react-router-dom": "^6.30.3",
|
|
"recharts": "^3.8.0",
|
|
"sonner": "^2.0.7",
|
|
"zod": "^4.4.3"
|
|
},
|
|
"devDependencies": {
|
|
"@axe-core/react": "^4.11.3",
|
|
"@playwright/test": "^1.49.0",
|
|
"@storybook/addon-a11y": "^10.4.0",
|
|
"@storybook/react-vite": "^10.4.0",
|
|
"@testing-library/jest-dom": "^6.9.1",
|
|
"@testing-library/react": "^16.3.2",
|
|
"@types/jest-axe": "^3.5.9",
|
|
"@types/react": "^19.2.14",
|
|
"@types/react-dom": "^19.2.3",
|
|
"@vitejs/plugin-react": "^6.0.1",
|
|
"autoprefixer": "^10.4.27",
|
|
"jest-axe": "^10.0.0",
|
|
"jsdom": "^29.0.0",
|
|
"orval": "^7.0.0",
|
|
"postcss": "^8.5.8",
|
|
"size-limit": "^11.2.0",
|
|
"@size-limit/file": "^11.2.0",
|
|
"storybook": "^10.4.0",
|
|
"tailwindcss": "^3.4.19",
|
|
"typescript": "^5.9.3",
|
|
"vite": "^8.0.10",
|
|
"vitest": "^4.1.0"
|
|
},
|
|
"overrides": {
|
|
"picomatch": "^4.0.4",
|
|
"lodash": ">=4.18.0"
|
|
}
|
|
}
|