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.
42 lines
1.5 KiB
TypeScript
42 lines
1.5 KiB
TypeScript
import { defineConfig } from 'vite'
|
|
import react from '@vitejs/plugin-react'
|
|
|
|
// https://vite.dev/config/
|
|
export default defineConfig({
|
|
plugins: [react()],
|
|
server: {
|
|
proxy: {
|
|
'/api': {
|
|
target: 'http://127.0.0.1:8000',
|
|
changeOrigin: true,
|
|
},
|
|
},
|
|
},
|
|
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,
|
|
},
|
|
})
|