83 lines
3.8 KiB
Markdown
83 lines
3.8 KiB
Markdown
# 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:
|
|
1. **Fixes a pre-existing JSX bug** in `client/src/pages/admin/HRManagement.tsx`
|
|
where 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>`.
|
|
2. 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 to `dist/`. Previously failed in `Transform 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 the `manualChunks` config.
|
|
- 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.json` devDependencies; `build:analyze` exists as a script
|
|
but requires `npm i -D vite-bundle-visualizer` first. 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-visualizer` to devDependencies (1 line in
|
|
`client/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), not `fix/p2-lazy`. Out of convention but not worth a
|
|
rename PR.
|