Vite 的工作原理是什么?和 Webpack 有什么区别?
Vite 的核心优势
开发阶段:利用浏览器原生 ESM,按需加载模块,无需打包。
开发阶段原理
浏览器请求 index.html
→ Vite 拦截 <script type="module" src="/src/main.js">
→ 按需编译每个模块
→ 浏览器通过 ESM import 链按需加载
→ 修改文件时只热更新对应模块// Vite dev server 拦截请求
// 请求 /src/main.js → Vite 编译 → 返回 ESM 格式
import { createApp } from 'vue' // → /node_modules/.vite/vue.js
import App from './App.vue' // → 编译 SFC 为 JS依赖预构建
Vite 使用 esbuild 预构建依赖(CJS → ESM):
首次启动:
1. 扫描 import 语句找到依赖
2. esbuild 预构建(比 Webpack 快 10-100 倍)
3. 缓存到 node_modules/.vite
4. 后续请求直接用缓存生产构建
开发用 ESM,但生产环境用 Rollup 打包:
// vite.config.js
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
export default defineConfig({
plugins: [vue()],
build: {
rollupOptions: {
output: {
manualChunks: {
vendor: ['vue', 'vue-router'],
ui: ['element-plus']
}
}
}
}
})为什么开发用 ESM 而生产用打包?
- 开发:ESM 按需加载,启动快,HMR 精准
- 生产:打包减少请求数、Tree Shaking、代码压缩
HMR 原理
1. 文件修改 → Vite 监听变化
2. 找到受影响的模块
3. 通过 WebSocket 通知浏览器
4. 浏览器重新请求变化的模块
5. 替换模块,保留应用状态Vite 配置
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
export default defineConfig({
plugins: [vue()],
// 路径别名
resolve: {
alias: {
'@': '/src'
}
},
// 开发服务器
server: {
port: 3000,
proxy: {
'/api': {
target: 'http://localhost:8080',
changeOrigin: true
}
}
},
// CSS 预处理器
css: {
preprocessorOptions: {
scss: { additionalData: '@import "@/styles/variables.scss";' }
}
},
// 环境变量
define: {
__APP_VERSION__: JSON.stringify('1.0.0')
}
})Webpack vs Vite
| 特性 | Webpack | Vite |
|---|---|---|
| 开发启动 | 全量打包,慢 | ESM 按需,极快 |
| 大项目启动 | 30s-2min | < 1s |
| HMR | 全模块链 | 精准单模块 |
| 配置 | 复杂 | 简单 |
| 生产打包 | Webpack | Rollup |
| 生态 | 最丰富 | 足够 |
| 学习曲线 | 高 | 低 |
Vite 插件生态
import vue from '@vitejs/plugin-vue' // Vue SFC
import react from '@vitejs/plugin-react' // React Fast Refresh
import legacy from '@vitejs/plugin-legacy' // 旧浏览器兼容
import { visualizer } from 'rollup-plugin-visualizer' // 包分析什么时候选 Vite
- 新项目(Vue/React/纯 TS)
- 追求开发体验
- 不需要兼容旧浏览器
什么时候选 Webpack
- 老项目迁移成本高
- 依赖 Webpack 特有插件
- 复杂的 Module Federation 场景