Vite(法语”快”的意思)已经成为现代前端项目的首选构建工具。它通过开发环境使用原生
ESM + esbuild 预构建,生产环境使用 Rollup
打包的双引擎架构,实现了极速的开发体验和优化的生产构建。本文将从架构设计讲起,深入分析
Dev Server 的工作原理、HMR 机制、生产构建流程,并手把手教你开发自定义
Vite 插件。
Vite 架构概览
graph TB
subgraph "Development 开发模式"
A[浏览器请求] --> B[Vite Dev Server]
B --> C[esbuild 预构建<br/>node_modules → ESM]
B --> D[原生 ESM<br/>按需编译源码]
B --> E[HMR WebSocket<br/>热模块替换]
end
subgraph "Production 生产模式"
F[vite build] --> G[Rollup 打包]
G --> H[代码分割 Code Splitting]
G --> I[Tree Shaking]
G --> J[CSS 提取 & 压缩]
G --> K[资源处理 & Hash]
end
style B fill:#646cff,color:#fff
style C fill:#ffcf00,color:#000
style G fill:#ef4444,color:#fff
为什么 Vite 这么快?
传统打包工具(如
Webpack)在开发模式下需要先打包所有模块,然后才能启动开发服务器。而 Vite
利用了两个关键优势:
原生 ESM:浏览器原生支持 ES Module,Vite
直接按需提供模块,无需打包
esbuild 预构建:用 Go 编写的 esbuild 比 JavaScript
打包器快 10-100 倍
sequenceDiagram
participant B as 浏览器
participant V as Vite Dev Server
participant E as esbuild
participant FS as 文件系统
Note over V: 启动时: 预构建 node_modules
V->>E: 预构建依赖 (react, lodash...)
E-->>V: ESM 格式的依赖缓存
B->>V: GET /src/App.tsx
V->>FS: 读取 App.tsx
FS-->>V: 源码
V->>V: 按需编译 (esbuild transform)
V-->>B: 编译后的 ESM 模块
B->>V: GET /node_modules/.vite/deps/react.js
V-->>B: 预构建的 React ESM (缓存)
Note over B,V: 文件修改
FS->>V: 文件变更事件
V->>V: 判断 HMR 边界
V->>B: WebSocket: HMR update
B->>V: GET /src/App.tsx?t=123456
V-->>B: 更新后的模块
Dev Server 深入
依赖预构建
Vite 在首次启动时,会使用 esbuild 将 node_modules
中的依赖预构建为 ESM 格式:
// Cleanup side effects import.meta.hot.dispose((data) => { // Store state for next update data.count = currentCount; clearInterval(timer); });
// Restore state after update if (import.meta.hot.data.count) { currentCount = import.meta.hot.data.count; }
// Invalidate: propagate update to parent import.meta.hot.invalidate();
// Full reload when HMR can't handle the change import.meta.hot.on('vite:beforeFullReload', () => { console.log('Full reload triggered'); }); }
框架 HMR 集成
graph TD
A[文件修改] --> B{文件类型?}
B -->|.vue| C["@vitejs/plugin-vue<br/>SFC HMR"]
B -->|.tsx/.jsx| D["@vitejs/plugin-react<br/>React Fast Refresh"]
B -->|.css| E[CSS HMR<br/>替换 style 标签]
B -->|.module.css| F[CSS Modules HMR<br/>更新 JS 模块]
C --> G[保持组件状态]
D --> G
E --> H[无需 JS 执行]
F --> I[更新样式映射]
style A fill:#646cff,color:#fff
style G fill:#2ecc71,color:#fff
style H fill:#2ecc71,color:#fff
1 2 3 4 5 6 7 8 9 10 11 12
// React Fast Refresh integration (simplified) // @vitejs/plugin-react automatically adds: if (import.meta.hot) { // Register component for React Fast Refresh window.$RefreshReg$(Component, 'Component'); window.$RefreshSig$();
import.meta.hot.accept((mod) => { // React Refresh runtime handles state preservation // Only re-renders changed components }); }
// Or use a function for more control manualChunks(id) { if (id.includes('node_modules')) { if (id.includes('react')) return'vendor-react'; if (id.includes('lodash')) return'vendor-lodash'; return'vendor'; // All other dependencies } },
graph TD
A[Vite 插件钩子] --> B[通用钩子<br/>兼容 Rollup]
A --> C[Vite 特有钩子]
B --> B1[buildStart]
B --> B2[resolveId]
B --> B3[load]
B --> B4[transform]
B --> B5[buildEnd]
C --> C1[config]
C --> C2[configResolved]
C --> C3[configureServer]
C --> C4[transformIndexHtml]
C --> C5[handleHotUpdate]
style A fill:#646cff,color:#fff
style B fill:#ef4444,color:#fff
style C fill:#10b981,color:#fff