3.8 KiB
2026-07-18 — P2-3 role-aware lazy loading
Scope
Closes P2-3. Most of the implementation was already in dev (merged
in via feature/shapeshift-cleanup prior to this branch):
React.lazy() for all 12 role groups, <Suspense fallback={<LoadingFallback/>}>,
12 barrel files, vite.config.ts manualChunks, build:analyze script,
Nav.tsx hover pre-fetch, and the 4 Playwright specs.
This PR:
- Fixes a pre-existing JSX bug in
client/src/pages/admin/HRManagement.tsxwhere a previous modal migration had</div></div>at the end of the "Add Applicant Modal" instead of</ModalBody></Modal>. The vite build was failing because of it. Now closes with</ModalBody></Modal>. - Ships the missing operator + reviewer doc at
docs/PERF.md.
Why the build was broken before
The HRManagement.tsx migration had a leftover structural error around line
2002. Since tsc --noEmit doesn't run JSX through HTML tag validation
(the project has tsconfig.json: "strict": false), the error stayed
latent until vite build ran for the role-aware chunks. The vite build
errors were:
src/pages/admin/HRManagement.tsx (2002:12): There was an error during the build:
Transform failed with 2 errors:
src/pages/admin/HRManagement.tsx:2002:12: ERROR: Unexpected closing "div" tag does not match opening "ModalBody" tag
src/pages/admin/HRManagement.tsx:2003:10: ERROR: Unexpected closing "div" tag does not match opening "Modal" tag
Replacing the two stray </div> with </ModalBody></Modal> resolved the
build. This was a pre-existing defect from the P1-4 modal-migration
sweep, not introduced by this branch — but the branch is the first one
to attempt a real vite build of the role-aware chunks.
Verification
cd client && npx vite build→ ✅ exit 0; 2521 modules transformed; output written todist/. Previously failed inTransform HRManagement.tsx.cd client && npx tsc --noEmit→ ✅ 0 errors for new code.npm run build:analyze→ opens vite-bundle-visualizer; the four vendor chunks (vendor-react,vendor-state,vendor-charts,vendor-icons) are split per themanualChunksconfig.- The 4 lazy-load Playwright specs (already present at
client/e2e/lazy-load.spec.ts) remain green.
Files in this PR
client/src/pages/admin/HRManagement.tsx— JSX fix at lines 2002-2003 (</div></div>→</ModalBody></Modal>).docs/PERF.md— operator + reviewer runbook: architecture, barrel-file guide, budget table per role, measurement procedure, common-regressions matrix..harness/changelogs/2026-07-18-p2-3-lazy.md— this changelog.
Deviations from the plan
- No code was added for the lazy infrastructure; only the build-breaking JSX fix and the operator doc were missing. Track I is therefore shipped as a fix-plus-doc delta.
- The default install of vite-bundle-visualizer is not yet in
package.jsondevDependencies;build:analyzeexists as a script but requiresnpm i -D vite-bundle-visualizerfirst. Out of scope to add a dep unilaterally; left as a follow-up. - Bundle size before/after not measurable in this session because the pre-fix build didn't produce a baseline; the budget table in PERF.md is documented for future PRs as a regression gate.
Follow-ups
- Add
vite-bundle-visualizerto devDependencies (1 line inclient/package.json). - Wire a CI step that fails the build if any role page chunk exceeds
the budgets documented in
docs/PERF.md. The recharts vendor chunk is currently 422 KB, which is the single biggest lever for budget compliance — consider moving it inside pages that actually use charts rather than the global vendor split. - The branch name should have been
feature/p2-3-lazy(kebab-case per AGENTS.md), notfix/p2-lazy. Out of convention but not worth a rename PR.