Development
Dev Server Features
- Native ESM serving (no bundling in dev)
- Instant HMR (Hot Module Replacement)
- TypeScript transpilation
- CSS HMR
- Vue/React/Svelte SFC support
Dependency Pre-Bundling
Vite pre-bundles dependencies for:
- CommonJS to ESM conversion
- Many-module dependencies (lodash-es)
- Faster cold starts
defineConfig({
optimizeDeps: {
include: [
'lodash-es', // Pre-bundle specific deps
'vue > @vue/runtime-dom', // Nested deps
],
exclude: ['@my/local-pkg'], // Skip pre-bundling
force: true, // Re-bundle on restart
esbuildOptions: {
target: 'esnext',
},
},
})Auto-discovery runs on server start. Use --force to re-bundle.
File System Access
defineConfig({
server: {
fs: {
strict: true, // Only allow listed dirs
allow: [
'../shared', // Allow parent directory
searchForWorkspaceRoot(process.cwd()), // Monorepo root
],
deny: ['.env', '.env.*', '*.pem'],
},
},
})HMR Configuration
defineConfig({
server: {
hmr: {
overlay: true, // Error overlay
port: 24678, // WebSocket port
protocol: 'ws', // 'ws' or 'wss'
host: 'localhost',
clientPort: 443, // For reverse proxy
},
},
})Disable HMR:
defineConfig({
server: {
hmr: false,
},
})HMR API Usage
// Basic accept
if (import.meta.hot) {
import.meta.hot.accept()
}
// Accept with handler
if (import.meta.hot) {
import.meta.hot.accept((newModule) => {
// Handle update
})
}
// Preserve state
let count = import.meta.hot?.data?.count ?? 0
if (import.meta.hot) {
import.meta.hot.dispose((data) => {
data.count = count
})
import.meta.hot.accept()
}
// Custom events (plugin communication)
if (import.meta.hot) {
import.meta.hot.on('custom:event', (payload) => {
console.log(payload)
})
}Web Workers
// Constructor (recommended)
const worker = new Worker(
new URL('./worker.ts', import.meta.url),
{ type: 'module' }
)
// Query suffix
import MyWorker from './worker?worker'
const worker = new MyWorker()
// Inline (bundled, no separate file)
import InlineWorker from './worker?worker&inline'Worker file:
// worker.ts
self.onmessage = (e: MessageEvent) => {
const result = heavyComputation(e.data)
self.postMessage(result)
}SharedWorker:
import SharedWorker from './shared?sharedworker'
const worker = new SharedWorker()Watch Mode
defineConfig({
server: {
watch: {
usePolling: true, // For network drives, containers
interval: 100,
ignored: ['**/node_modules/**', '**/.git/**'],
},
},
})HTTPS
import basicSsl from '@vitejs/plugin-basic-ssl'
defineConfig({
plugins: [basicSsl()],
server: {
https: true,
},
})Custom certificates:
import fs from 'node:fs'
defineConfig({
server: {
https: {
key: fs.readFileSync('localhost-key.pem'),
cert: fs.readFileSync('localhost.pem'),
},
},
})Network Access
vite --host # Expose to network
vite --host 0.0.0.0 # Specific interfacedefineConfig({
server: {
host: true, // Same as --host
port: 3000,
strictPort: true, // Fail if port taken
},
})Performance Tips
Explicit file extensions - Reduce resolve operations
import './Component.tsx' // Instead of './Component'Warm up frequently used files
server: { warmup: { clientFiles: ['./src/main.ts', './src/App.vue'], }, }Avoid barrel files - Direct imports are faster
import { util } from './utils/util.ts' // Not './utils'Limit watched files
server: { watch: { ignored: ['**/large-folder/**'], }, }Disable unused features
css: { devSourcemap: false }
Profiling
vite --debug # Debug logs
vite --debug plugin-transform # Transform times
vite --profile # CPU profileUse vite-plugin-inspect for plugin debugging.