#vite /
Why Is Vite So Fast? Analyzing Its Principles and Advantages
Deeply understand the core principles behind Vite's speed, from ESM native support to dependency pre-bundling, revealing the design philosophy of the next-generation frontend build tool.
Goal
Understand the core principles behind Vite's speed and why it can replace Webpack as the preferred choice for next-generation frontend build tools.
Background
Webpack's Problem
# A medium-sized React project
webpack startup time: 8.2 seconds
webpack HMR: 1.5 seconds
# After the project grows
webpack startup time: 45 seconds
webpack HMR: 5-8 seconds
The root cause of Webpack's slow startup: It needs to bundle all modules before the development server can start.
Webpack's workflow:
1. Read all source files
2. Parse dependency graph
3. Transform code (Babel, TypeScript, etc.)
4. Bundle into bundles
5. Start development server
Users have to wait for all 5 steps before seeing the page
Vite's Solution
Vite's workflow:
1. Start development server (milliseconds)
2. Compile on-demand when browser requests
3. Use ESM native module loading
Users see the page almost instantly
Core Principles Behind Vite's Speed
1. ESM Native Support
Modern browsers natively support ES Modules:
<!-- Browser can run this code directly -->
<script type="module">
import { createApp } from './app.js'
import { router } from './router.js'
createApp(App).use(router).mount('#app')
</script>
// app.js - Browser will automatically request this file
import { ref } from 'vue'
export function createApp() { /* ... */ }
Key insight: If browsers can run ESM directly, why do we need bundling?
2. Dependency Pre-bundling
ESM is great, but there's one problem: Most npm packages are not in ESM format.
// lodash exports CJS modules
const _ = require('lodash')
// Vite's solution: dependency pre-bundling
// Use esbuild to convert CJS dependencies to ESM
// And merge small modules to reduce request count
# When Vite starts:
# 1. Scan package.json dependencies
# 2. Pre-bundle with esbuild (usually < 100ms)
# 3. Cache to node_modules/.vite
# Benefits of pre-bundling:
# - CJS → ESM conversion
# - Merge small modules (lodash has 600+ files)
# - Cache for faster subsequent startups
3. On-demand Compilation
// Webpack: compile all files at startup
// src/
// ├── App.tsx ← compile
// ├── components/
// │ ├── Header.tsx ← compile
// │ ├── Footer.tsx ← compile
// │ └── ... (100 components) ← all compiled
// Vite: only compile files requested by browser
// Browser requests App.tsx → compile App.tsx
// Browser requests Header.tsx → compile Header.tsx
// Other files? Wait until browser needs them
Performance Comparison
Cold Startup Time
Project: React + TypeScript, 200 components
Webpack 5: 12.3 seconds
Vite: 0.8 seconds
Improvement: 93%
Hot Module Replacement Time
Modify a component's styles
Webpack 5: 1.8 seconds
Vite: 0.1 seconds
Improvement: 94%
Large Project Cold Startup
Project: Vue 3 + TypeScript, 1000 components
Webpack 5: 58 seconds
Vite: 2.1 seconds
Improvement: 96%
Vite's Architecture
┌─────────────────────────────────────┐
│ Vite Dev Server │
│ ┌─────────────────────────────┐ │
│ │ HTTP Server (connect) │ │
│ └─────────────────────────────┘ │
│ ┌─────────────────────────────┐ │
│ │ Plugin Pipeline │ │
│ │ - resolveId │ │
│ │ - load │ │
│ │ - transform │ │
│ └─────────────────────────────┘ │
│ ┌─────────────────────────────┐ │
│ │ Module Graph (on-demand) │ │
│ └─────────────────────────────┘ │
└─────────────────────────────────────┘
│
▼
┌─────────────────────────────────────┐
│ esbuild │
│ - Dependency pre-bundling │
│ - TypeScript transpilation │
│ - JSX transformation │
└─────────────────────────────────────┘
Vite Configuration Deep Dive
Basic Configuration
// vite.config.js
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
export default defineConfig({
plugins: [vue()],
// Development server
server: {
port: 3000,
open: true,
proxy: {
'/api': {
target: 'http://localhost:8080',
changeOrigin: true
}
}
},
// Dependency pre-bundling
optimizeDeps: {
include: ['lodash', 'axios'],
exclude: ['your-big-local-package']
},
// Build configuration
build: {
outDir: 'dist',
sourcemap: true,
rollupOptions: {
output: {
manualChunks: {
vendor: ['vue', 'vue-router'],
utils: ['lodash', 'axios']
}
}
}
},
// Aliases
resolve: {
alias: {
'@': '/src'
}
}
})
CSS Processing
export default defineConfig({
css: {
preprocessorOptions: {
scss: {
additionalData: `@import "@/styles/variables.scss";`
}
},
modules: {
localsConvention: 'camelCase'
}
}
})
Vite vs Webpack vs Create React App
| Feature | Vite | Webpack | CRA | |---------|------|---------|-----| | Cold startup | Fast | Slow | Slow | | HMR | Extremely fast | Slow | Medium | | Configuration complexity | Low | High | None (hidden) | | Flexibility | High | Very high | Low | | Ecosystem maturity | High | Very high | High | | TypeScript | Native support | Needs loader | Built-in | | ESM | Native support | Needs configuration | Not supported |
Advantages in Real Projects
1. Fast Development Experience
# Start a new project
npm create vite@latest my-app -- --template vue-ts
cd my-app
npm install
npm run dev
# From creation to seeing the page: < 3 seconds
2. Seamless TypeScript Support
// No need to configure tsconfig.json
// No need to install ts-loader
// Vite + esbuild supports it directly
// Write TypeScript directly, Vite handles it automatically
const greeting: string = 'Hello, World!'
3. Rich Plugin Ecosystem
// Using Vite plugins
import vue from '@vitejs/plugin-vue'
import vueJsx from '@vitejs/plugin-vue-jsx'
import Components from 'unplugin-vue-components/vite'
import AutoImport from 'unplugin-auto-import/vite'
export default defineConfig({
plugins: [
vue(),
vueJsx(),
Components({
resolvers: [ElementPlusResolver()]
}),
AutoImport({
imports: ['vue', 'vue-router'],
dts: 'src/auto-imports.d.ts'
})
]
})
When Shouldn't You Use Vite?
- Need to support IE11: Vite doesn't support it
- Node.js below 14: Vite requires Node.js 14+
- Need very complex build configurations: Webpack is more flexible
- Legacy project migration: If the project deeply depends on Webpack ecosystem
Summary
The core reasons why Vite is fast:
- ESM native support: Leverages browser capabilities, no bundling needed
- Dependency pre-bundling: Uses esbuild (written in Go) for fast dependency processing
- On-demand compilation: Only processes files requested by the browser
- esbuild replaces Babel: esbuild written in Go is 100x faster than Babel
Vite is not "a faster Webpack" — it's a completely different build philosophy. It moves bundling work from the development phase to the build phase, qualitatively improving the development experience.
For new projects, Vite should be your default choice.