nexus/.planning/phases/26-pwa-performance/26-01-SUMMARY.md
Nexus Dev e93922e4a0 docs(26-01): complete lazy-loading and vendor chunk splitting plan
- Created 26-01-SUMMARY.md with task commits, decisions, and verification results
- STATE.md: advanced plan 2->3, recorded metrics and decisions
- ROADMAP.md: updated phase 26 progress (2 of 5 summaries)
- REQUIREMENTS.md: marked PERF-01 complete (PERF-05 already complete)
2026-04-04 03:55:48 +00:00

109 lines
4.4 KiB
Markdown

---
phase: 26-pwa-performance
plan: 01
subsystem: ui
tags: [react, vite, performance, lazy-loading, code-splitting, bundle-optimization]
requires:
- phase: 25-file-system
provides: "Completed UI feature set that needed bundling optimization"
provides:
- "React.lazy code splitting for all 37 page components in App.tsx"
- "Suspense boundary with Skeleton fallback for route transitions"
- "Manual vendor chunk splitting in Vite: vendor-react, vendor-router, vendor-query, vendor-markdown"
- "Reduced initial bundle load via route-level lazy splitting"
affects:
- 26-02-PLAN
- 26-03-PLAN
- 26-04-PLAN
tech-stack:
added: []
patterns:
- "React.lazy with .then(m => ({ default: m.NamedExport })) pattern for named-export pages"
- "Suspense boundary wrapping Routes block for route-level loading fallback"
- "Vite manualChunks for stable vendor bundle caching"
key-files:
created: []
modified:
- ui/src/App.tsx
- ui/vite.config.ts
key-decisions:
- "All 37 page components use named exports, so lazy imports use .then(m => ({ default: m.X })) module re-mapping"
- "Suspense boundary placed around Routes (not each Route) for single loading boundary"
- "vendor-react, vendor-router, vendor-query, vendor-markdown as manualChunks — no @mdxeditor/editor (avoids circular deps)"
- "OnboardingWizard kept as eager import — renders outside Routes, always needed for app shell"
patterns-established:
- "Named-export lazy pattern: lazy(() => import('./pages/X').then(m => ({ default: m.X })))"
- "Suspense fallback uses Skeleton component from @/components/ui/skeleton"
requirements-completed: [PERF-01, PERF-05]
duration: 4min
completed: 2026-04-02
---
# Phase 26 Plan 01: Lazy Loading and Vendor Chunk Splitting Summary
**React.lazy code splitting for all 37 page components plus Vite manualChunks for react, react-dom, react-router-dom, @tanstack/react-query, react-markdown vendor bundles**
## Performance
- **Duration:** ~4 min
- **Started:** 2026-04-02T01:57:13Z
- **Completed:** 2026-04-02T02:01:00Z
- **Tasks:** 2
- **Files modified:** 2
## Accomplishments
- Converted all 37 eager page imports in App.tsx to `React.lazy` with named-export re-mapping pattern
- Wrapped `<Routes>` with `<Suspense>` boundary using `<Skeleton>` fallback for route chunk loading
- Added `build.rollupOptions.output.manualChunks` to vite.config.ts producing 4 stable vendor chunks
- Build verified: 4 vendor chunks present in dist/assets/ with no circular dependency errors
## Task Commits
1. **Task 1: Convert App.tsx page imports to React.lazy with Suspense** - `da35021a` (feat)
2. **Task 2: Add manual vendor chunk splitting to Vite config** - `31f25b34` (feat)
## Files Created/Modified
- `ui/src/App.tsx` - Replaced 37 eager named-export page imports with React.lazy + Suspense boundary wrapping Routes
- `ui/vite.config.ts` - Added build.rollupOptions.output.manualChunks for vendor-react, vendor-router, vendor-query, vendor-markdown
## Decisions Made
- All page files use `export function PageName()` named exports (not default exports), so lazy imports use `.then(m => ({ default: m.X }))` module re-mapping to satisfy React.lazy's default export requirement
- Suspense boundary placed at the outer `<Routes>` level rather than per-route — single loading state for any route chunk load
- `@mdxeditor/editor` intentionally excluded from manualChunks per plan guidance (complex internal imports risk circular dependency errors)
- `rehype-highlight` excluded (replaced by manual highlight.js usage in Phase 25)
- `OnboardingWizard` kept eager — renders outside `<Routes>` and is always present in the app shell
## Deviations from Plan
None — plan executed exactly as written. The named-export lazy pattern was correctly anticipated by the plan in step 4 of Task 1.
## Issues Encountered
None — build succeeded on first attempt with all 4 vendor chunks produced and no circular dependency errors.
## User Setup Required
None — no external service configuration required.
## Next Phase Readiness
- Route-level code splitting complete: each page loads as its own chunk on demand
- Vendor chunks cached separately from application code (stable browser caching for react, router, query, markdown)
- Ready for Plan 02 (service worker / PWA manifest) and Plan 03 (offline support)
- Main bundle still ~1.7 MB due to mermaid/cytoscape/katex; Plans 02-04 address further splitting or deferral
---
*Phase: 26-pwa-performance*
*Completed: 2026-04-02*