Vite 在开发环境 和生产环境中采用了完全不同的打包策略,这是其高性能的核心设计之一。
🌐 1. 开发环境(Development):按需动态编译,不打包
✅ 核心机制:基于原生 ESM 的服务器
- 不进行完整打包
- 启动时仅启动一个轻量级 HTTP 服务器(基于 connect)
- 利用浏览器对
<script type="module">
的原生支持,按需加载模块
🔧 工作流程:
- 浏览器请求
index.html
- HTML 中的
import /src/main.js
触发模块加载 - Vite 服务器拦截每个模块请求(如
/src/utils.js
) - 动态编译该文件(例如:TS → JS、Vue → JS)
- 返回编译后的 JavaScript 内容
⚙️ 关键优化点:
步骤 | 技术实现 |
---|---|
依赖预构建 | 使用 esbuild 把 node_modules 文件夹中原本不被浏览器直接支持的 CommonJS 或 UMD 格式的第三方库,自动转换成现代浏览器可以原生加载的 ES 模块(ESM)格式 |
按需转换 | 只有被访问的文件才编译,未使用的代码不会参与构建 |
HMR 热更新 | 通过 WebSocket 监听文件变化,精确替换模块,无需刷新页面 |
💡 举例:
import _ from 'lodash'
→ 被重写为/@modules/lodash.js
→ 由 esbuild 预构建后提供 ESM 版本
vite dev
运行原理:
- 扫描你的代码中所有来自
node_modules
的导入(如import _ from 'lodash'
) - 收集需要预构建的依赖列表
- 使用 esbuild 将它们转换为 ESM 并打包成单个文件
HMR
热更新原理:
1. 启动服务器并建立 WebSocket 连接
- Vite 开发服务器启动时,同时开启一个 WebSocket 服务(如
ws://localhost:24678
) - 浏览器通过注入的客户端脚本自动连接:
ini
js
const ws = new WebSocket(`ws://localhost:${port}`);
2. 监听文件变化(使用 chokidar)
- 服务器监听项目根目录下的所有源码文件
- 当你保存修改(如
src/utils.js
),立即触发 change 事件
3. 分析模块依赖图谱
- Vite 维护了模块之间的导入关系(Module Graph)
- 知道哪些模块引用了被修改的文件
- 例如:
main.js
→ imports →utils.js
,修改utils.js
就会影响main.js
4. 发送更新消息到浏览器
- 服务器通过 WebSocket 推送更新通知:
json
json
{
"type": "update",
"updates": [
{
"type": "js-update",
"path": "/src/utils.js",
"timestamp": 1734567890123
}
]
}
5. 拉取最新模块代码
- 浏览器接收到消息后,用时间戳作为缓存破坏参数,重新请求模块:
csharp
js
await import('/src/utils.js?t=1734567890123');
- 服务器返回编译后的最新 JavaScript 内容
6. 替换旧模块并更新视图
-
执行新模块代码
-
框架层处理更新:
- Vue :通过
import.meta.hot.accept()
触发组件重新渲染 - React:结合 Fast Refresh 保留状态并更新组件
- CSS :替换
<style>
标签内容,无需重载页面
- Vue :通过
📦 2. 生产环境(Production):使用 Rollup 打包
虽然开发时不打包,但在生产环境中 Vite 会进行完整的打包优化。
✅ 构建命令:
bash
vite build
🛠️ 底层工具:Rollup
- Vite 的生产构建是基于 Rollup 实现的
- Rollup 更适合库和应用的静态分析与 tree-shaking
- 支持代码分割、懒加载、CSS 提取等高级功能
📈 输出结果:
优化项 | 说明 |
---|---|
Tree Shaking | 删除未使用的代码 |
Code Splitting | 自动拆分 chunk,支持动态导入 |
Minification | 使用 Terser 压缩 JS,CSSNano 压缩 CSS |
Asset Hashing | 添加 content hash 实现缓存失效 |
Gzip/Brotli 预警 | 可配合插件生成压缩版本 |
🆚 对比总结
特性 | 开发环境(Dev) | 生产环境(Build) |
---|---|---|
是否打包 | ❌ 不打包 | ✅ 完整打包 |
构建工具 | esbuild(预构建依赖)+ 原生 ESM | Rollup |
启动速度 | 极快(毫秒级) | 较慢(取决于项目大小) |
模块处理 | 按需动态编译 | 全量静态分析 |
输出产物 | 无 bundle,直接服务源码 | dist/ 目录包含优化后的静态资源 |
HMR 支持 | ✅ WebSocket 实现热更新 | ❌ 静态文件,不支持 HMR |
适用场景 | 快速开发调试 | 部署上线 |
🧩 示例配置:vite.config.js
php
js
import { defineConfig } from 'vite';
import vue from '@vitejs/plugin-vue';
export default defineConfig({
plugins: [vue()],
// 开发服务器配置
server: {
port: 3000,
open: true
},
// 生产构建配置
build: {
outDir: 'dist',
minify: 'terser',
sourcemap: false,
rollupOptions: {
output: {
chunkFileNames: 'assets/js/[name]-[hash].js',
assetFileNames: 'assets/[ext]/[name]-[hash].[ext]'
}
}
}
});
✅ 总结
- 开发阶段:Vite 利用现代浏览器的 ESM 能力,做到"零打包",极大提升启动和热更新速度。
- 生产阶段:切换到 Rollup 进行专业级打包,确保输出高度优化、体积小、性能好。