Skip to main content

ADR-034: Vite Build System

Status

Implemented

Date

2025-01-16 (Retrospective)

Decision Makers

  • Frontend Team - Build tooling
  • DevOps Team - CI/CD integration

Layer

Frontend

  • ADR-006: React 18 with Material-UI v7

Supersedes

  • Create React App (migrated to Vite)

Depends On

None

Context

Frontend build tooling impacts developer experience:

  1. Development Speed: Fast HMR for rapid iteration
  2. Build Performance: Quick production builds
  3. Bundle Optimization: Efficient code splitting
  4. Modern Standards: ESM-first, TypeScript native
  5. Plugin Ecosystem: Rich extensibility

Requirements:

  • Sub-second HMR updates
  • Production builds under 60 seconds
  • Tree shaking for MUI components
  • Source maps for debugging
  • Environment variable handling

Decision

We adopt Vite as the frontend build system:

Key Design Decisions

  1. Vite 7.x: Latest version with esbuild
  2. ESM Development: Native ES modules in dev
  3. Rollup Production: Optimized bundling for prod
  4. React Plugin: @vitejs/plugin-react
  5. TypeScript Native: No separate compilation step

Configuration

// vite.config.ts
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';

export default defineConfig({
plugins: [react()],
server: {
port: 3333,
proxy: {
'/api': {
target: 'http://localhost:8888',
changeOrigin: true,
},
},
},
build: {
outDir: 'dist',
sourcemap: true,
rollupOptions: {
output: {
manualChunks: {
vendor: ['react', 'react-dom'],
mui: ['@mui/material', '@mui/icons-material'],
query: ['@tanstack/react-query'],
},
},
},
},
resolve: {
alias: {
'@': '/src',
},
},
});

Environment Variables

# .env
VITE_API_URL=http://localhost:8888
VITE_ENVIRONMENT=development
// Usage
const apiUrl = import.meta.env.VITE_API_URL;

Build Scripts

{
"scripts": {
"dev": "vite",
"build": "vite build",
"build:prod": "tsc && vite build --mode production",
"preview": "vite preview"
}
}

Consequences

Positive

  • Instant HMR: <50ms updates during development
  • Fast Builds: Production builds in ~30 seconds
  • Modern Output: ESM bundles for modern browsers
  • Great DX: Excellent error messages
  • Tree Shaking: MUI reduced by 60%+

Negative

  • Breaking Changes: Vite major versions have changes
  • Plugin Compatibility: Not all webpack plugins work
  • Learning Curve: Different from CRA patterns
  • Config Complexity: More configuration options

Neutral

  • Browser Support: Modern browsers only (acceptable)
  • Test Integration: Works with Vitest (same ecosystem)

Alternatives Considered

1. Create React App

  • Approach: Zero-config React setup
  • Rejected: Slow, maintenance mode, limited customization

2. webpack 5 Custom

  • Approach: Custom webpack configuration
  • Rejected: Complex, slower development server

3. Parcel

  • Approach: Zero-config bundler
  • Rejected: Less mature React support

Implementation Status

  • Core implementation complete
  • Tests written and passing
  • Documentation updated
  • Migration/upgrade path defined
  • Monitoring/observability in place

Implementation Details

  • Config: frontend/vite.config.ts
  • TypeScript: frontend/tsconfig.json
  • Scripts: frontend/package.json
  • Build Output: frontend/dist/

LLM Council Review

Review Date: 2025-01-16 Confidence Level: High (100%) Verdict: APPROVED WITH CONFIG CHANGES

Quality Metrics

  • Consensus Strength Score (CSS): 0.90
  • Deliberation Depth Index (DDI): 0.85

Council Feedback Summary

Migration to Vite 7 is universally approved. However, the proposed manualChunks strategy with a monolithic MUI chunk is an anti-pattern that fights modern code-splitting.

Key Concerns Identified:

  1. MUI Chunk Anti-Pattern: Forcing all MUI into one chunk loads heavy components (DataGrid) on lightweight pages (Login)
  2. Static Arrays Brittle: Hardcoded ['react', 'react-dom'] doesn't catch sub-dependencies
  3. Missing Visualization Splitting: SRE charts (Recharts, D3) should be route-split, not vendored

Required Modifications:

  1. Remove Hardcoded MUI Chunk: Let Rollup split MUI per route via React.lazy()
  2. Use Function-Based manualChunks:
    manualChunks: (id) => {
    if (id.includes('node_modules') && (id.includes('react') || id.includes('react-dom'))) {
    return 'vendor-react';
    }
    if (id.includes('@tanstack/react-query')) {
    return 'vendor-query';
    }
    // Let Vite handle MUI & charts via route splitting
    }
  3. Add Bundle Analyzer: Use rollup-plugin-visualizer to verify chunk sizes
  4. Set Target: Use es2020 or esnext for internal tools to reduce polyfill bloat
  5. Direct Imports: Avoid barrel exports; use import { Button } from '@mui/material/Button'

Modifications Applied

  1. Documented function-based manualChunks pattern
  2. Removed MUI from vendor chunk recommendation
  3. Added bundle analyzer requirement
  4. Documented direct import pattern

Council Ranking

  • gemini-3-pro: Best Response (code splitting)
  • claude-opus-4.5: Strong (MUI concerns)
  • gpt-5.2: Good (caching strategy)

References


ADR-034 | Frontend Layer | Implemented