Vite 1.0 在 2020 年釋出後,"秒級啟動"讓很多人驚歎。本文深入分析 Vite 能做到這一點的底層原理,以及它和 webpack dev server 的根本區別。
傳統 webpack 的瓶頸
webpack 在啟動時必須先打包再服務:
啟動 webpack dev server:
1. 解析所有入口和依賴樹(可能幾千個模組)
2. 轉換每個模組(TS→JS、Less→CSS 等)
3. 將所有模組打包成 bundle
4. 啟動 HTTP 服務,提供 bundle
→ 冷啟動時間:幾十秒到幾分鐘(大型專案)
這意味著你改一個檔案,webpack 需要重新構建受影響的整個 chunk,然後通過 WebSocket 傳送更新。
Vite 的 No-bundle 方案
啟動 Vite dev server:
1. 僅預構建 node_modules 中的依賴(esbuild,極快)
2. 啟動 HTTP 服務
→ 冷啟動時間:< 1 秒
瀏覽器請求頁面時:
按需轉換被請求的模組(而不是提前打包所有模組)
這依賴於現代瀏覽器原生支援 ES Module:
<!-- index.html -->
<script type="module" src="/src/main.ts"></script>
瀏覽器看到 type="module" 後,會自行解析 import 語句併發起請求。Vite 只需要在服務端轉換被請求的檔案:
// 瀏覽器請求 /src/App.vue
// Vite 服務端接收請求,即時轉換:
// 1. 解析 .vue 檔案的 template、script、style
// 2. 將 template 編譯成 render function
// 3. 返回 ES module 格式的 JS
依賴預構建
node_modules 中的包通常是 CommonJS 格式,瀏覽器不能直接 import。Vite 在首次啟動時用 esbuild 預構建這些依賴:
# Vite 啟動時的預構建
node_modules/lodash-es → .vite/lodash-es.js (合併成單檔案,減少請求數)
node_modules/vue → .vite/vue.js
...
esbuild 是 Go 語言編寫的打包工具,速度比 webpack 快 10-100 倍,所以這個步驟通常在幾百毫秒內完成。
HMR 實現原理
Vite 的 HMR 比 webpack 更精準:
// Vite HMR 協議
// 當 src/components/Button.vue 被修改時:
// 1. Vite 檔案監聽器檢測到變化
// 2. 分析該檔案的 HMR 邊界
// 3. 僅使這個檔案的模組快取失效
// 4. 通過 WebSocket 通知瀏覽器
// 5. 瀏覽器重新請求這個檔案(而不是整個 bundle)
// 元件內接收 HMR
if (import.meta.hot) {
import.meta.hot.accept("./Button.vue", (newModule) => {
// 替換模組
});
}
Vue 和 React 的 HMR 外掛(@vitejs/plugin-vue、@vitejs/plugin-react)自動處理元件級熱更新,開發者通常不需要手寫上面的程式碼。
與 webpack 的對比
| | webpack dev server | Vite | | ---------- | ---------------------- | -------------- | | 冷啟動 | 慢(需要打包所有模組) | 快(按需轉換) | | HMR 速度 | 毫秒~秒(依專案大小) | 始終毫秒級 | | 生產構建 | webpack | Rollup | | 配置複雜度 | 高 | 低 | | 相容性 | IE11+ | 現代瀏覽器 |
vite.config.js 基礎配置
import { defineConfig } from "vite";
import vue from "@vitejs/plugin-vue";
export default defineConfig({
plugins: [vue()],
server: {
port: 3000,
proxy: {
"/api": {
target: "http://localhost:8080",
changeOrigin: true,
},
},
},
resolve: {
alias: { "@": "/src" },
},
});
總結
Vite 的快不是優化了 webpack,而是繞過了打包這一步。利用瀏覽器原生 ESM + esbuild 預構建,將"先打包再服務"變成了"按需轉換"。這個思路對於理解下一代前端工具鏈非常重要。