Code splitting and dynamic imports to reduce bundle size.
Quick Reference
CRITICAL priority - Reduces Time to Interactive and Largest Contentful Paint.Key patterns:
Dynamic imports (next/dynamic or React.lazy)
Defer third-party scripts
Conditional module loading
Preload on hover for perceived speed
When to split:
Components >50KB bundled
Heavy libraries (Monaco, Chart.js, PDF viewers)
Behind user interaction (modals, tabs)
Dynamic Imports
Vite Apps (React.lazy)
Next.js Apps (next/dynamic)
Defer Third-Party Libraries
Load analytics and tracking after hydration:Next.js:
Vite:
Conditional Module Loading
Load modules only when features are activated:
Preload on Hover
Improve perceived performance by preloading on hover:
Measuring Bundle Size
Vite
Next.js
Common Heavy Libraries
Split these aggressively:
Monaco Editor (~300KB)
Chart.js (~200KB)
PDF.js (~150KB)
Rich text editors (Slate, Draft.js)
Video players
Map libraries (Mapbox, Leaflet)
Route-Based Splitting
Vite
Next.js
Routes are automatically code-split in Next.js App Router:
Chunk Configuration (Vite)
Shells and remotes build with the Module Federation plugin, which removes manualChunks and codeSplitting.groups from the Vite config and logs that it ignored them. Do not add vendor or feature chunks there; split with lazy routes and dynamic imports instead.
Each shared package (React, Apollo, the router) gets its own chunk through the federation plugin.
The shell factory puts @prepared911/ui in a ui-singleton chunk and the third-party code it reaches in a ui-vendor chunk, so browsers keep both cached until the UI or its dependencies change.
A new output chunk group goes in a plugin's outputOptions hook. The mfe-module-federation agent skill ("How chunks are formed") has the rules, and Bundle size shows how to find what grew a chunk.