From 7389ddb62c9a99aa1615876799d32c6c58eb4b31 Mon Sep 17 00:00:00 2001 From: anti Date: Fri, 24 Apr 2026 18:29:49 -0400 Subject: [PATCH] =?UTF-8?q?chore(web/build):=20split=20vendor=20chunks=20?= =?UTF-8?q?=E2=80=94=20705=20kB=20main=20bundle=20=E2=86=92=20246=20kB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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. --- decnet_web/vite.config.ts | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/decnet_web/vite.config.ts b/decnet_web/vite.config.ts index 83775466..89ce888c 100644 --- a/decnet_web/vite.config.ts +++ b/decnet_web/vite.config.ts @@ -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, + }, })