feat(frontend): route-level code splitting (#105) #183
Loading…
Reference in a new issue
No description provided.
Delete branch "feat/105-route-code-splitting"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Fixes #105. Third of the v3.5.0 (Frontend Platform & PWA) milestone, after #180 and #181.
Why
App.jsxeagerly imported all 20 pages, so every route shipped in one 685 kB chunk. A player opening the dashboard downloaded the admin panel and the entirereact-markdown/micromark toolchain — pulled in byWikiArticle, its sole consumer — before seeing anything.What changed
React.lazy, with a single<Suspense>around the route table.AuthGuardstill gates protected routes, so a page chunk is only fetched once its route matches.Loginstays eager — judgement call, documented in the file. It's small, andAuthGuardbounces every logged-out visitor straight to it as soon as the/api/meprobe resolves; splitting it would add a chunk round-trip and a fallback flash to the most common cold-start path.components/LoadingScreen.jsx; both share it now.Before / after
−441 kB (−64%) raw, −94 kB (−55%) gzipped off the initial download.
The markdown toolchain is now isolated in the 169.21 kB
WikiArticlechunk (gzip 46.42 kB), fetched only by people who actually open a wiki article. Other notable splits:CampaignDetail67.73 kB,Admin42.91 kB,SessionDetail31.37 kB,Dashboardjust 10.56 kB.Acceptance criteria
Initial JS payload for the dashboard route drops substantially — 685.50 → 244.25 kB entry (gzip 172.36 → 78.32); a dashboard visitor now adds only the 10.56 kB
Dashboardchunk plus small shared api chunks, instead of the whole app.react-markdownis absent from the entry chunk — verified by grepping the built assets, not assumed:micromark,mdast,hast,remark,fromMarkdown,characterReferenceAll page tests pass with lazy routes — 97/97. No harness changes needed; the suite already awaits its queries, so lazy resolution didn't break it.
Navigating to every route works in a production build (
vite previewsmoke check) — 20/20 routes serve 200, 24/24 built assets serve 200, andindex.htmlreferences the entry chunk.Verification
Run in node:20, matching CI:
npm run lint→ exit 0, no output.npx vitest run→ 97/97.npx vite build→ succeeds, no chunk-size warning.Honest limitation on the smoke check: it runs
vite previewand asserts every route and every built asset serves 200 — it proves the SPA and all 23 lazy chunks are served and reachable, and that no lazy import path is broken. It does not execute JS in a real browser (no headless browser in the toolchain). The 97 jsdom tests do render the app through the lazy boundary, which covers the execution side.🤖 Generated with Claude Code
App.jsx eagerly imported all 20 pages, so every route shipped in one 685 kB chunk. A player opening the dashboard downloaded the admin panel and the whole react-markdown/micromark toolchain (pulled in by WikiArticle, its sole consumer) before seeing anything. Convert the page imports to React.lazy and wrap the route table in a single Suspense boundary. AuthGuard still gates protected routes, so a page chunk is only fetched once its route matches. Login stays eager: it is small, and AuthGuard bounces every logged-out visitor straight to it once the /api/me probe resolves, so splitting it would add a chunk round-trip and a fallback flash to the most common cold-start path. The Suspense fallback reuses AuthGuard's existing loading UI rather than inventing a second spinner; that markup moves into components/LoadingScreen.jsx and both now share it. Entry chunk: before 685.50 kB (gzip 172.36 kB) 1 JS chunk after 244.25 kB (gzip 78.32 kB) + 23 lazy chunks -441 kB / -64% raw, -94 kB / -55% gzipped, and rollup's >500 kB chunk warning is gone. The markdown toolchain is now isolated in the 169.21 kB WikiArticle chunk, downloaded only by wiki readers — verified by grepping the built assets: micromark/mdast/hast/remark appear in the WikiArticle chunk and are absent from the entry chunk. No test-harness changes were needed; the suite already awaits its queries, so lazy resolution didn't break it. Verified in node:20: lint clean, 97/97 tests, and a vite preview smoke check of the production build — all 20 routes serve 200 and all 24 built assets serve 200. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>