Project setup, plugins, HMR, build configuration, environment variables, SSR, and framework integration.
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
import path from 'path';
export default defineConfig({
plugins: [react()],
// Path aliases
resolve: {
alias: {
'@': path.resolve(__dirname, './src'),
'@components': path.resolve(__dirname, './src/components'),
},
},
// Development server
server: {
port: 3000,
open: true,
host: true, // Listen on all addresses (LAN)
strictPort: true, // Error if port is taken
hmr: {
overlay: true, // Show error overlay
},
proxy: {
'/api': {
target: 'http://localhost:8080',
changeOrigin: true,
rewrite: (path) => path.replace(/^\/api/, ''),
},
'/ws': {
target: 'ws://localhost:8080',
ws: true,
},
},
},
// Build options
build: {
outDir: 'dist',
sourcemap: true,
minify: 'esbuild', // 'esbuild' (default) or 'terser'
target: 'es2020',
rollupOptions: {
output: {
manualChunks: {
'react-vendor': ['react', 'react-dom'],
'router': ['react-router-dom'],
},
},
},
chunkSizeWarningLimit: 500,
cssCodeSplit: true,
},
// CSS options
css: {
preprocessorOptions: {
scss: {
additionalData: '@use "@/styles/variables" as *;',
},
},
},
// Environment variables
envPrefix: 'VITE_',
});| Feature | Vite | Webpack |
|---|---|---|
| Dev Server Start | <300ms (native ESM) | 10-60s (full bundle) |
| HMR Speed | Instant (ESM) | Slow (rebundles) |
| Config | Simple defaults | Complex config |
| Production Build | Rollup (tree-shaking) | Webpack bundle |
| Ecosystem | Growing | Mature, many plugins |
| Migration | Easy from CRA | Manual config |
| Command | Purpose |
|---|---|
| npm create vite@latest | Scaffold new project |
| npm run dev | Start dev server with HMR |
| npm run build | Production build |
| npm run preview | Preview production build |
| vite optimize | Pre-bundle dependencies |
// ── Official Framework Plugins ──
import react from '@vitejs/plugin-react';
import vue from '@vitejs/plugin-vue';
import svelte from '@sveltejs/vite-plugin-svelte';
// React plugin (includes JSX, Fast Refresh)
export default defineConfig({
plugins: [react({
babel: {
plugins: ['babel-plugin-styled-components'],
},
})],
});
// ── Environment Variables ──
// Only VITE_ prefixed variables are exposed to client code
console.log(import.meta.env.VITE_API_URL); // Available
console.log(import.meta.env.DB_PASSWORD); // NOT available (no VITE_ prefix)
// Built-in env variables:
// import.meta.env.MODE // 'development' | 'production'
// import.meta.env.BASE_URL // Base URL from config
// import.meta.env.PROD // true in production
// import.meta.env.DEV // true in development
// import.meta.env.SSR // true during SSR// ── .env files (loaded by Vite automatically) ──
// .env (all modes)
VITE_APP_TITLE=My App
VITE_API_URL=https://api.example.com
// .env.development (dev mode only)
VITE_API_URL=http://localhost:8080
VITE_DEBUG=true
// .env.production (production only)
VITE_API_URL=https://api.example.com
VITE_SENTRY_DSN=https://key@sentry.io/123
// .env.local (git-ignored, all modes)
VITE_SECRET_KEY=local-secret
// Priority: .env.local > .env.[mode].local > .env.[mode] > .env// ── Optimized Production Build ──
export default defineConfig({
build: {
// Output directory
outDir: 'dist',
// Source maps for debugging
sourcemap: 'hidden',
// Minification: 'esbuild' (fast) or 'terser' (more options)
minify: 'esbuild',
// Target browsers
target: 'es2020',
// Chunk size warning
chunkSizeWarningLimit: 500,
rollupOptions: {
input: {
main: path.resolve(__dirname, 'index.html'),
admin: path.resolve(__dirname, 'admin.html'),
},
output: {
// Manual chunks for vendor splitting
manualChunks(id) {
if (id.includes('node_modules')) {
if (id.includes('react')) return 'react-vendor';
if (id.includes('lodash')) return 'lodash';
return 'vendor';
}
},
// File naming
chunkFileNames: 'assets/js/[name]-[hash].js',
entryFileNames: 'assets/js/[name]-[hash].js',
assetFileNames: 'assets/[ext]/[name]-[hash].[ext]',
},
},
// CSS handling
cssCodeSplit: true,
cssMinify: true,
},
});// ── Server-Side Rendering (SSR) Setup ──
// server.js (Node.js)
import fs from 'node:fs';
import path from 'node:path';
import { fileURLToPath } from 'node:url';
const __dirname = path.dirname(fileURLToPath(import.meta.url));
const isProduction = process.env.NODE_ENV === 'production';
async function createServer() {
const { createServer: createViteServer } = await import('vite');
const vite = await createViteServer({
server: { middlewareMode: true },
appType: 'custom',
});
app.use('*', async (req, res) => {
try {
let template = fs.readFileSync(path.resolve(__dirname, 'index.html'), 'utf-8');
template = await vite.transformIndexHtml(req.url, template);
const { render } = await vite.ssrLoadModule('/src/entry-server.tsx');
const { pipe } = render(req.url, template);
res.status(200).set({ 'Content-Type': 'text/html' });
pipe(res);
} catch (e) {
vite.ssrFixStacktrace(e);
res.status(500).end(e.message);
}
});
app.listen(3000);
}
createServer();| File | Description |
|---|---|
| dist/index.html | Entry HTML with injected scripts |
| dist/assets/js/*.js | JavaScript bundles |
| dist/assets/css/*.css | Extracted CSS |
| dist/assets/[ext]/* | Images, fonts, etc. |
| Plugin | Framework |
|---|---|
| @vitejs/plugin-react | React + JSX + Fast Refresh |
| @vitejs/plugin-vue | Vue 3 SFC + HMR |
| @vitejs/plugin-svelte | Svelte + HMR |
| @vitejs/plugin-vue-jsx | Vue JSX support |
| @vitejs/plugin-legacy | Legacy browser support |
Vite serves source code as native ES modules (ESM). The browser parses imports natively, so Vite only needs to serve the requested file and transform it on-demand. Webpack bundles the entire application before serving, which gets slow as projects grow. Vite pre-bundles dependencies with esbuild (10-100x faster than Webpack's loader pipeline). HMR only updates the changed module and its imports, not the entire bundle.
No. Vite uses esbuild for dev-time transformations (JSX, TypeScript, SCSS) and Rollup for production builds. esbuild is written in Go and compiles 10-100x faster than JavaScript-based tools. Rollup handles tree-shaking, code splitting, and chunk optimization for production bundles.