"Vite lightning-fast build tool with instant HMR, ESM-first architecture, and zero-config setup for modern web development"
Resources
1Install
npx skillscat add bobmatnyc/claude-mpm-skills/vite-build-tool Install via the SkillsCat registry.
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-tsEssential 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/.viteConfiguration
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.comUsage 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); // booleanvite-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-legacyEssential 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_URLFrom 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 configSSR (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 installIssue: 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.jsonDebug Mode
# Verbose logging
DEBUG=vite:* vite
# Specific debug scopes
DEBUG=vite:deps vite
DEBUG=vite:hmr vite
DEBUG=vite:config viteAdvanced 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