ai-code-battle/web/vite.config.ts
jedarden c5a83cbe32 feat(web): code splitting per §16.7 — reduce app entry chunk 84% (10KB → 1.6KB gz)
Extract all inline page renderers from app.ts into lazy-loaded modules and
remove 500+ lines of duplicated replay viewer code. Every route now uses
dynamic import() so page code loads on-demand.

Changes:
- Remove duplicated replay viewer (renderReplayPage, initReplayViewer) from
  app.ts — now uses lazy import from pages/replay.ts
- Extract Watch Hub, Compete Hub, Season Detail, Docs, and 404 pages into
  their own modules (pages/watch-hub.ts, compete-hub.ts, season-detail.ts,
  docs.ts, not-found.ts)
- app.ts is now a pure routing module (~120 lines) with only lazy loaders
- Update vite.config.ts manualChunks: add replay-page, home, leaderboard
  chunks; add node_modules guard to prevent vendor code in page chunks
- All §16.7 budget targets pass: app.js 1.6KB (target 30KB), replay 13KB
  (target 80KB), sandbox 8.4KB (target 20KB), agentation separate

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-21 12:41:33 -04:00

70 lines
2.3 KiB
TypeScript

import { defineConfig } from 'vite'
import { resolve } from 'path'
export default defineConfig({
root: '.',
build: {
outDir: 'dist',
sourcemap: true,
rollupOptions: {
input: {
main: resolve(__dirname, 'index.html'),
app: resolve(__dirname, 'app.html'),
embed: resolve(__dirname, 'embed.html'),
},
output: {
manualChunks(id) {
if (id.includes('node_modules')) return;
// Agentation: React + agentation library (lazy-loaded only on /feedback)
if (id.includes('react') || id.includes('agentation')) {
return 'agentation';
}
// Replay viewer chunk (canvas renderer + win probability)
if (id.includes('replay-viewer') || id.includes('win-probability')) {
return 'replay-viewer';
}
// Replay page (uses replay-viewer, separate from the viewer chunk itself)
if (id.includes('pages/replay')) {
return 'replay-page';
}
// Sandbox chunk (includes engine orchestration + WASM loader)
if (id.includes('pages/sandbox')) {
return 'sandbox';
}
// Evolution page (live polling, SVG lineage tree, island grid)
if (id.includes('pages/evolution')) {
return 'evolution';
}
// Blog pages (markdown parsing)
if (id.includes('pages/blog')) {
return 'blog';
}
// Clip maker (video/GIF export)
if (id.includes('pages/clip-maker')) {
return 'clip-maker';
}
// Series/predictions (chart-heavy)
if (id.includes('pages/series') || id.includes('pages/predictions')) {
return 'charts';
}
// Feedback page (includes its own replay viewer + triggers agentation load)
if (id.includes('pages/feedback')) {
return 'feedback';
}
// Home page (hero, playlists carousel, season bar, evolution mini)
if (id.includes('pages/home')) {
return 'home';
}
// Leaderboard (rating table)
if (id.includes('pages/leaderboard')) {
return 'leaderboard';
}
},
},
},
},
server: {
port: 3000,
},
})