很多观点只停留在“Vite 用 ESM,所以快”,但真正的核心其实是 开发服务器架构 + Module Graph + HMR 机制。
一、Vite 的核心架构
Vite 的开发服务器本质是一个 按需编译的 HTTP Server。
整体架构可以理解为:
Browser
│
HTTP Request
│
Vite Dev Server
│
Plugin Pipeline
│
Transform (esbuild / plugins)
│
Return ESM
关键点:
浏览器驱动编译
也就是说:
浏览器请求什么
Vite 才编译什么
例如:
index.html
├── main.ts
├── App.vue
├── router.ts
└── store.ts
浏览器请求流程:
GET /main.ts
GET /App.vue
GET /router.ts
GET /store.ts
每个模块都是 独立编译返回。
二、Module Graph(Vite 的核心数据结构)
Vite 在内存里维护了一张 模块依赖图:
App.vue
│
├── Button.vue
│ │
│ └── icon.svg
│
└── utils.ts
这个结构叫:
Module Graph
模块节点大概结构:
interface ModuleNode {
url: string
importers: Set<ModuleNode>
importedModules: Set<ModuleNode>
}
作用:
1️⃣ 记录模块依赖关系
2️⃣ 精准 HMR 更新
3️⃣ 快速失效缓存
三、Vite HMR 为什么是毫秒级
在 Webpack 中:
修改文件
↓
重新编译 bundle
↓
重新计算依赖
↓
HMR
但在 Vite:
修改 Button.vue
↓
找到 ModuleGraph 节点
↓
找到 importers
↓
只更新受影响模块
示例:
App.vue
│
└── Button.vue
修改 Button.vue:
只更新 Button.vue
不会重新编译整个项目。
四、Vite 的 Transform Pipeline
Vite 的模块处理是一个 插件流水线:
request
│
resolveId
│
load
│
transform
│
return code
例如 .vue 文件:
App.vue
│
Vue Plugin
│
compile SFC
│
返回 JS module
处理后类似:
import { render } from './App.vue?type=template'
export default {
render
}
所以浏览器其实加载的是:
JS Module
五、为什么 node_modules 要预构建
浏览器加载 ESM 有一个问题:
lodash-es
可能会产生:
600+ 请求
所以 Vite 用:
esbuild 做 依赖预构建。
node_modules
↓
esbuild
↓
合并成单个 ESM
例如:
lodash
react
react-dom
可能会被打包成:
vendor.js
这样浏览器只请求一次。
六、Vite Dev Server 的缓存系统
Vite 有三层缓存:
1 node_modules 预构建缓存
目录:
node_modules/.vite
内容:
deps
metadata.json
作用:
避免重复 esbuild
2 transform 缓存
每个模块会缓存 transform 结果:
source → transform → cache
如果文件没变:
直接返回缓存
3 HTTP cache
浏览器也会缓存:
ETag
304 Not Modified
减少网络传输。
七、为什么 Webpack 很难做到 Vite 这么快
Webpack 的设计是:
Bundle-first architecture
流程:
Dependency Graph
↓
Chunk Graph
↓
Bundle
即:
必须先打包
浏览器才能运行
这意味着:
开发阶段也必须打包
所以即使优化:
HMR
DLL
cache
thread-loader
也很难突破。
八、Vite 是“浏览器驱动构建”
Vite 把构建职责从 构建工具转移到了 浏览器。
传统模式:
Bundler → Browser
Vite 模式:
Browser → Vite Server
浏览器变成了:
模块加载器
九、为什么说 Vite 是前端工程化的范式升级
前端构建工具其实经历了三代:
第一代:任务流
代表:
- Grunt
- Gulp
模式:
task pipeline
第二代:Bundler
代表:
- Webpack
- Rollup
模式:
bundle everything
第三代:Native ESM Dev Server
代表:
- Vite
- Snowpack
模式:
browser-driven compilation
十、很多人不知道的一个 Vite 细节
Vite 不是完全不打包。
在生产环境:
Vite 使用:
Rollup
原因:
浏览器加载:
2000 modules
生产环境会:
chunk splitting
tree shaking
code splitting
最终生成:
assets/
vendor.js
main.js
十一、Vite 的未来方向
未来构建工具其实在往 Rust / Go 方向走。
例如:
- Turbopack
- Rspack
- Parcel
趋势:
JS Bundler
↓
Native Bundler
因为 JS 写构建工具性能始终有限。
十二、最本质的总结
Vite 快不是因为:
工具优化
而是因为:
架构改变
传统:
源码 → bundle → 浏览器
Vite:
源码 → 浏览器 → 按需编译