Agent skill
vite-build-tool
Vite lightning-fast build tool with instant HMR, ESM-first architecture, and zero-config setup for modern web development
Install this agent skill to your Project
npx add-skill https://github.com/bobmatnyc/claude-mpm-skills/tree/main/toolchains/javascript/build/vite
SKILL.md
Vite Build Tool Skill
progressive_disclosure: entry_point: summary: "Lightning-fast build tool with instant HMR and ESM-first architecture for modern web development" when_to_use: - "When building React/Vue/Svelte/Preact applications" - "When needing instant HMR (Hot Module Replacement)" - "When migrating from webpack/CRA/Parcel" - "When setting up TypeScript projects with zero config" - "When building component libraries or UI frameworks" quick_start: - "npm create vite@latest my-app" - "Select framework: React/Vue/Svelte/Vanilla" - "cd my-app && npm install && npm run dev" essential_commands: - "vite: Start dev server with instant HMR" - "vite build: Production build with Rollup" - "vite preview: Preview production build locally" token_estimate: entry: 75 full: 4000
Core Concepts
Why Vite?
ESM-First Architecture
- No bundling in development - serves native ESM
- Instant cold server start (no matter project size)
- Lightning-fast HMR that stays fast as app grows
- Rollup-based production builds with optimal code splitting
Key Advantages
- Dev Speed: 10-100x faster than webpack (no bundling)
- Zero Config: TypeScript, JSX, CSS modules out-of-box
- Framework Agnostic: React, Vue, Svelte, Preact, Lit
- Plugin Ecosystem: Rollup plugins + Vite-specific plugins
- Modern by Default: ESM, dynamic imports, top-level await
Quick Start
Create New Project
# Interactive creation
npm create vite@latest
# With template
npm create vite@latest my-app -- --template react-ts
npm create vite@latest my-app -- --template vue
npm create vite@latest my-app -- --template svelte-ts
# Available templates:
# vanilla, vanilla-ts
# react, react-ts, react-swc, react-swc-ts
# vue, vue-ts
# svelte, svelte-ts
# preact, preact-ts
# lit, lit-ts
Essential Commands
# Development server (instant start)
npm run dev
vite --port 3000 --host 0.0.0.0
# Production build
npm run build
vite build --mode production
# Preview production build
npm run preview
vite preview --port 8080
# Clear cache (dependency pre-bundling)
rm -rf node_modules/.vite
Configuration
Basic vite.config.ts
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
export default defineConfig({
plugins: [react()],
// Dev server
server: {
port: 3000,
open: true,
cors: true,
proxy: {
'/api': {
target: 'http://localhost:8000',
changeOrigin: true,
rewrite: (path) => path.replace(/^\/api/, '')
}
}
},
// Build options
build: {
outDir: 'dist',
sourcemap: true,
minify: 'terser',
rollupOptions: {
output: {
manualChunks: {
vendor: ['react', 'react-dom'],
utils: ['lodash-es', 'date-fns']
}
}
}
},
// Path aliases
resolve: {
alias: {
'@': '/src',
'@components': '/src/components',
'@utils': '/src/utils'
}
}
});
Framework-Specific Configs
React + TypeScript + SWC
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react-swc';
import path from 'path';
export default defineConfig({
plugins: [
react({
// Enable Fast Refresh
fastRefresh: true,
// SWC optimizations
tsDecorators: true
})
],
resolve: {
alias: {
'@': path.resolve(__dirname, './src')
}
},
build: {
target: 'es2020',
rollupOptions: {
output: {
manualChunks(id) {
if (id.includes('node_modules')) {
if (id.includes('react') || id.includes('react-dom')) {
return 'react-vendor';
}
return 'vendor';
}
}
}
}
}
});
Vue 3 + TypeScript
import { defineConfig } from 'vite';
import vue from '@vitejs/plugin-vue';
import vueJsx from '@vitejs/plugin-vue-jsx';
export default defineConfig({
plugins: [
vue(),
vueJsx() // For JSX/TSX in Vue
],
resolve: {
alias: {
'@': '/src',
'vue': 'vue/dist/vue.esm-bundler.js'
}
},
// Vue-specific optimizations
optimizeDeps: {
include: ['vue', 'vue-router', 'pinia']
}
});
Svelte + TypeScript
import { defineConfig } from 'vite';
import { svelte } from '@sveltejs/vite-plugin-svelte';
export default defineConfig({
plugins: [
svelte({
compilerOptions: {
dev: process.env.NODE_ENV !== 'production'
},
hot: {
preserveLocalState: true
}
})
],
build: {
target: 'es2020',
minify: 'esbuild'
}
});
Environment Variables
.env Files
# .env (loaded in all cases)
VITE_APP_TITLE=My App
# .env.local (local overrides, gitignored)
VITE_API_KEY=secret-key
# .env.development
VITE_API_URL=http://localhost:8000
# .env.production
VITE_API_URL=https://api.production.com
Usage in Code
// TypeScript: Define env types
interface ImportMetaEnv {
readonly VITE_APP_TITLE: string;
readonly VITE_API_URL: string;
readonly VITE_API_KEY: string;
}
interface ImportMeta {
readonly env: ImportMetaEnv;
}
// Access variables (MUST start with VITE_)
console.log(import.meta.env.VITE_API_URL);
console.log(import.meta.env.MODE); // 'development' or 'production'
console.log(import.meta.env.DEV); // boolean
console.log(import.meta.env.PROD); // boolean
vite-env.d.ts
/// <reference types="vite/client" />
interface ImportMetaEnv {
readonly VITE_APP_TITLE: string;
readonly VITE_API_URL: string;
readonly VITE_API_KEY: string;
}
interface ImportMeta {
readonly env: ImportMetaEnv;
}
Plugin Ecosystem
Official Plugins
# React
npm install -D @vitejs/plugin-react # Babel-based
npm install -D @vitejs/plugin-react-swc # SWC-based (faster)
# Vue
npm install -D @vitejs/plugin-vue
npm install -D @vitejs/plugin-vue-jsx
# Svelte
npm install -D @sveltejs/vite-plugin-svelte
# Legacy browser support
npm install -D @vitejs/plugin-legacy
Essential Community Plugins
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react-swc';
import tsconfigPaths from 'vite-tsconfig-paths';
import { VitePWA } from 'vite-plugin-pwa';
import compression from 'vite-plugin-compression';
import { visualizer } from 'rollup-plugin-visualizer';
export default defineConfig({
plugins: [
react(),
// TypeScript paths from tsconfig.json
tsconfigPaths(),
// PWA support
VitePWA({
registerType: 'autoUpdate',
manifest: {
name: 'My App',
short_name: 'App',
theme_color: '#ffffff'
}
}),
// Gzip/Brotli compression
compression({
algorithm: 'brotliCompress',
ext: '.br'
}),
// Bundle size visualization
visualizer({
open: true,
gzipSize: true,
brotliSize: true
})
]
});
TypeScript Configuration
tsconfig.json for Vite
{
"compilerOptions": {
"target": "ES2020",
"useDefineForClassFields": true,
"lib": ["ES2020", "DOM", "DOM.Iterable"],
"module": "ESNext",
"skipLibCheck": true,
/* Bundler mode */
"moduleResolution": "bundler",
"allowImportingTsExtensions": true,
"resolveJsonModule": true,
"isolatedModules": true,
"noEmit": true,
"jsx": "react-jsx",
/* Linting */
"strict": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"noFallthroughCasesInSwitch": true,
/* Path aliases */
"baseUrl": ".",
"paths": {
"@/*": ["./src/*"],
"@components/*": ["./src/components/*"]
}
},
"include": ["src"],
"references": [{ "path": "./tsconfig.node.json" }]
}
tsconfig.node.json (for config files)
{
"compilerOptions": {
"composite": true,
"skipLibCheck": true,
"module": "ESNext",
"moduleResolution": "bundler",
"allowSyntheticDefaultImports": true
},
"include": ["vite.config.ts"]
}
CSS & Asset Handling
CSS Modules
// Component.module.css
.button {
background: blue;
color: white;
}
// Component.tsx
import styles from './Component.module.css';
export function Button() {
return <button className={styles.button}>Click</button>;
}
PostCSS Configuration
// postcss.config.js
export default {
plugins: {
'postcss-nesting': {},
'autoprefixer': {},
'cssnano': {
preset: 'default'
}
}
};
Sass/SCSS
npm install -D sass
// Just import - Vite handles it
import './styles.scss';
// Vite config for global variables
export default defineConfig({
css: {
preprocessorOptions: {
scss: {
additionalData: `@import "@/styles/variables.scss";`
}
}
}
});
Static Assets
// Import as URL
import imgUrl from './assets/logo.png';
console.log(imgUrl); // '/assets/logo.abc123.png'
// Import as string (raw)
import svgRaw from './icon.svg?raw';
console.log(svgRaw); // '<svg>...</svg>'
// Import as Web Worker
import Worker from './worker?worker';
const worker = new Worker();
// Public directory (not processed)
// public/favicon.ico → /favicon.ico
<img src="/favicon.ico" />
Build Optimization
Code Splitting
export default defineConfig({
build: {
rollupOptions: {
output: {
// Manual chunks for better caching
manualChunks(id) {
if (id.includes('node_modules')) {
// Split by package
if (id.includes('react') || id.includes('react-dom')) {
return 'react-vendor';
}
if (id.includes('@mui')) {
return 'mui-vendor';
}
if (id.includes('lodash')) {
return 'lodash-vendor';
}
return 'vendor';
}
},
// Naming patterns
chunkFileNames: 'assets/js/[name]-[hash].js',
entryFileNames: 'assets/js/[name]-[hash].js',
assetFileNames: 'assets/[ext]/[name]-[hash].[ext]'
}
},
// Chunk size warnings
chunkSizeWarningLimit: 1000,
// Minification
minify: 'terser',
terserOptions: {
compress: {
drop_console: true,
drop_debugger: true
}
}
}
});
Dependency Pre-bundling
export default defineConfig({
optimizeDeps: {
// Force include (for dynamic imports)
include: [
'react',
'react-dom',
'lodash-es'
],
// Force exclude (keep unbundled)
exclude: [
'your-local-package'
],
// esbuild options
esbuildOptions: {
target: 'es2020',
define: {
global: 'globalThis'
}
}
}
});
Library Mode
// Build as library/package
import { defineConfig } from 'vite';
import { resolve } from 'path';
export default defineConfig({
build: {
lib: {
entry: resolve(__dirname, 'src/index.ts'),
name: 'MyLibrary',
fileName: (format) => `my-library.${format}.js`,
formats: ['es', 'cjs', 'umd']
},
rollupOptions: {
// Externalize deps that shouldn't be bundled
external: ['react', 'react-dom'],
output: {
globals: {
react: 'React',
'react-dom': 'ReactDOM'
}
}
}
}
});
Migration Guides
From Create React App (CRA)
# 1. Remove CRA
npm uninstall react-scripts
# 2. Install Vite
npm install -D vite @vitejs/plugin-react
# 3. Update package.json scripts
{
"scripts": {
"dev": "vite",
"build": "vite build",
"preview": "vite preview"
}
}
// 4. Create vite.config.ts
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
export default defineConfig({
plugins: [react()],
server: {
port: 3000
},
build: {
outDir: 'build' // CRA uses 'build'
}
});
<!-- 5. Update index.html (move to root, remove %PUBLIC_URL%) -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Vite + React</title>
</head>
<body>
<div id="root"></div>
<script type="module" src="/src/main.tsx"></script>
</body>
</html>
// 6. Update environment variables
// CRA: REACT_APP_API_URL
// Vite: VITE_API_URL
// Before (CRA)
process.env.REACT_APP_API_URL
// After (Vite)
import.meta.env.VITE_API_URL
From Webpack
// webpack.config.js → vite.config.ts
// Webpack concepts → Vite equivalents:
// - entry → index.html + <script src="main.tsx">
// - output.path → build.outDir
// - resolve.alias → resolve.alias (same!)
// - module.rules → plugins (for file types)
// - optimization.splitChunks → build.rollupOptions.output.manualChunks
// - DefinePlugin → define config option
// - devServer → server config
SSR (Server-Side Rendering)
Basic SSR Setup
// vite.config.ts
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
export default defineConfig({
plugins: [react()],
build: {
// SSR build
ssr: true,
outDir: 'dist/server'
}
});
// server.ts (Express + Vite SSR)
import express from 'express';
import { createServer as createViteServer } from 'vite';
async function createServer() {
const app = express();
const vite = await createViteServer({
server: { middlewareMode: true },
appType: 'custom'
});
app.use(vite.middlewares);
app.use('*', async (req, res) => {
const url = req.originalUrl;
try {
// Load template
let template = await vite.transformIndexHtml(
url,
fs.readFileSync('index.html', 'utf-8')
);
// Load SSR entry
const { render } = await vite.ssrLoadModule('/src/entry-server.tsx');
// Render app
const appHtml = await render(url);
// Inject into template
const html = template.replace(`<!--ssr-outlet-->`, appHtml);
res.status(200).set({ 'Content-Type': 'text/html' }).end(html);
} catch (e) {
vite.ssrFixStacktrace(e);
res.status(500).end(e.stack);
}
});
app.listen(3000);
}
createServer();
Performance Best Practices
Dev Server Optimization
export default defineConfig({
server: {
// Faster dependency resolution
fs: {
strict: false,
allow: ['..']
},
// WebSocket connection
hmr: {
overlay: true,
clientPort: 3000
}
},
// Faster pre-bundling
optimizeDeps: {
force: false, // Only rebuild on deps change
include: ['large-dependencies']
},
// Faster transforms
esbuild: {
logOverride: { 'this-is-undefined-in-esm': 'silent' }
}
});
Build Performance
export default defineConfig({
build: {
// Faster builds (esbuild vs terser)
minify: 'esbuild',
// Disable source maps in production
sourcemap: false,
// Target modern browsers only
target: 'es2020',
// Reduce rollup overhead
rollupOptions: {
cache: true
},
// Report compressed size (slower but informative)
reportCompressedSize: false
}
});
Smart Code Splitting
// Dynamic imports for route-based splitting
const Home = lazy(() => import('./pages/Home'));
const About = lazy(() => import('./pages/About'));
// Component-level splitting
const HeavyChart = lazy(() => import('./components/HeavyChart'));
// Conditional loading
const AdminPanel = lazy(() =>
import(/* @vite-ignore */ './admin/Panel')
);
Debugging
Common Issues
Issue: Module not found
# Clear dependency cache
rm -rf node_modules/.vite
npm install
Issue: HMR not working
// Check vite.config.ts
export default defineConfig({
server: {
hmr: {
overlay: true
},
watch: {
usePolling: true // For Docker/WSL
}
}
});
Issue: Build errors but dev works
# Check for:
# - TypeScript errors (tsc --noEmit)
# - Import paths (case sensitivity)
# - Missing dependencies in package.json
Debug Mode
# Verbose logging
DEBUG=vite:* vite
# Specific debug scopes
DEBUG=vite:deps vite
DEBUG=vite:hmr vite
DEBUG=vite:config vite
Advanced Patterns
Multi-page App
import { defineConfig } from 'vite';
import { resolve } from 'path';
export default defineConfig({
build: {
rollupOptions: {
input: {
main: resolve(__dirname, 'index.html'),
admin: resolve(__dirname, 'admin/index.html'),
docs: resolve(__dirname, 'docs/index.html')
}
}
}
});
Custom Plugin
import { Plugin } from 'vite';
export function myPlugin(): Plugin {
return {
name: 'my-plugin',
// Transform code
transform(code, id) {
if (id.endsWith('.custom')) {
return {
code: transformCode(code),
map: null
};
}
},
// Handle HMR
handleHotUpdate({ file, server }) {
if (file.endsWith('.custom')) {
server.ws.send({
type: 'custom',
event: 'update'
});
}
},
// Modify config
config(config, env) {
return {
define: {
__BUILD_TIME__: JSON.stringify(new Date().toISOString())
}
};
}
};
}
Monorepo Support
// packages/app/vite.config.ts
import { defineConfig } from 'vite';
export default defineConfig({
resolve: {
alias: {
'@shared': '../../packages/shared/src'
}
},
optimizeDeps: {
include: [
'@workspace/shared' // Pre-bundle workspace deps
]
},
server: {
fs: {
allow: ['../..'] // Allow serving from monorepo root
}
}
});
Integration Examples
Vite + React + TypeScript + Tailwind
npm create vite@latest my-app -- --template react-ts
cd my-app
npm install -D tailwindcss postcss autoprefixer
npx tailwindcss init -p
// tailwind.config.js
export default {
content: [
"./index.html",
"./src/**/*.{js,ts,jsx,tsx}",
],
theme: {
extend: {},
},
plugins: [],
};
Vite + Testing (Vitest)
npm install -D vitest @testing-library/react jsdom
// vite.config.ts
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
export default defineConfig({
plugins: [react()],
test: {
globals: true,
environment: 'jsdom',
setupFiles: './src/test/setup.ts',
coverage: {
provider: 'v8',
reporter: ['text', 'json', 'html']
}
}
});
Quick Reference
Essential Configuration Options
export default defineConfig({
// Base public path
base: '/my-app/',
// Modes: 'development' | 'production'
mode: 'production',
// Define global constants
define: {
__APP_VERSION__: JSON.stringify('1.0.0')
},
// Public directory
publicDir: 'public',
// Cache directory
cacheDir: 'node_modules/.vite',
// Log level
logLevel: 'info' // 'info' | 'warn' | 'error' | 'silent'
});
Common Plugin Combinations
// React + TypeScript + PWA + Analytics
import react from '@vitejs/plugin-react-swc';
import { VitePWA } from 'vite-plugin-pwa';
import tsconfigPaths from 'vite-tsconfig-paths';
export default defineConfig({
plugins: [
react(),
tsconfigPaths(),
VitePWA({
registerType: 'autoUpdate'
})
]
});
Related Skills
When using Vite, consider these complementary skills (available in the skill library):
- React: React framework integration - use Vite's optimized React plugin for fast development
- Vue: Vue framework integration - leverage Vite's native Vue support and SFC compilation
- Svelte: Svelte framework integration - combine Svelte's compile-time optimizations with Vite's speed
- TypeScript: TypeScript configuration - configure TypeScript with Vite for type-safe development
- Vitest: Testing with Vite - use Vitest for lightning-fast unit testing with Vite's transform pipeline
Resources
Official Documentation
- Vite Guide: https://vitejs.dev/guide/
- Config Reference: https://vitejs.dev/config/
- Plugin API: https://vitejs.dev/guide/api-plugin.html
Community
- Awesome Vite: https://github.com/vitejs/awesome-vite
- Vite Rollup Plugins: https://vite-rollup-plugins.patak.dev/
Migration Tools
- CRA to Vite: https://github.com/vitejs/vite/discussions/3802
- Webpack to Vite: https://github.com/originjs/webpack-to-vite
Recommended Agent Skills
Expand your agent's capabilities with these related and highly-rated skills.
bad-example-skill
ANTI-PATTERN - Example showing violations of self-containment (DO NOT COPY)
example-framework-skill
Example of a properly self-contained skill following all best practices
systematic-debugging
Systematic debugging methodology emphasizing root cause analysis over quick fixes
verification-before-completion
Run verification commands and confirm output before claiming success
Root Cause Tracing
Systematically trace bugs backward through call stack to find original trigger
Brainstorming Ideas Into Designs
Interactive idea refinement using Socratic method to develop fully-formed designs
Didn't find tool you were looking for?