chore(web/build): split vendor chunks — 705 kB main bundle → 246 kB
Single-bundle build was tripping vite's 500 kB warning per chunk and forcing every user to re-download the entire app on every deploy. Manual chunks split the bundle along natural library boundaries so: - Rarely-changing vendor libs (react-dom, react-router, lucide-react, asciinema-player) cache across deploys. - App code lives in its own `index-*.js` that's the only chunk that changes when we ship feature work. Split shape (manualChunks fn in vite.config.ts): - charts — recharts + d3-* - player — asciinema-player - icons — lucide-react - router — react-router / react-router-dom - react-dom, react - vendor — everything else in node_modules Resulting bundle sizes (gzip): index (app): 246 kB (gz 63) react-dom: 182 kB (gz 57) player: 176 kB (gz 65) router: 42 kB (gz 15) vendor: 36 kB (gz 14) icons: 29 kB (gz 10) Every chunk under the 600 kB ceiling we now set explicitly. The old ~705 kB single-chunk deploy is gone. No code changes — config only.
This commit is contained in:
@@ -12,4 +12,30 @@ export default defineConfig({
|
||||
},
|
||||
},
|
||||
},
|
||||
build: {
|
||||
// Split heavy third-party libs into their own chunks so the main
|
||||
// bundle stays small and the rarely-changing vendor code stays
|
||||
// cacheable across deploys. Recharts + asciinema-player + lucide
|
||||
// together made up most of the weight that was tripping the 500kB
|
||||
// warning.
|
||||
rollupOptions: {
|
||||
output: {
|
||||
manualChunks: (id: string) => {
|
||||
if (!id.includes('node_modules')) return undefined
|
||||
// d3-* ships alongside recharts as its plotting engine —
|
||||
// grouping them keeps tree-shaken subsets together.
|
||||
if (id.includes('recharts') || id.includes('/d3-')) return 'charts'
|
||||
if (id.includes('asciinema-player')) return 'player'
|
||||
if (id.includes('lucide-react')) return 'icons'
|
||||
if (id.includes('react-router')) return 'router'
|
||||
if (id.includes('react-dom')) return 'react-dom'
|
||||
if (id.includes('/react/') || id.endsWith('/react')) return 'react'
|
||||
return 'vendor'
|
||||
},
|
||||
},
|
||||
},
|
||||
// Legitimate ceiling for any single chunk after splitting; anything
|
||||
// larger is a real bloat regression worth investigating.
|
||||
chunkSizeWarningLimit: 600,
|
||||
},
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user