Vite vs Webpack:为什么 Vite 这么快

Webpack 不是慢,Vite 也不是魔法。小明用“构建 vs 开发”的视角拆开两者:依赖预构建、原生 ESM、按需编译、HMR、缓存与生产构建链路,帮你在项目规模、生态与团队约束里做出最稳的选择。

18 分钟阅读
小明

Vite vs Webpack:为什么 Vite 这么快

你一定经历过这种“开发者精神污染”:

  • 你改了一行 CSS
  • 你按下保存
  • 你看着终端开始转圈
  • 你开始怀疑人生:我只是换了个颜色,为什么要等 20 秒?

然后你换到 Vite:

  • 冷启动像开闪现
  • HMR 像“意念更新”

于是江湖传言出现了:

Vite 快,因为它更先进;Webpack 慢,因为它老。

这话有一半对,一半会害人。

真正的答案是:它们解决的问题不完全一样

  • Webpack 更像“把一切打包成一个可以交付的产物”的系统
  • Vite 更像“开发时尽可能快,生产时再认真打包”的系统

今天我们把“快”讲清楚:不是口号,是机制。


1. 先定调:为什么“开发体验”会慢?慢在哪?

开发阶段的慢,通常来自这两件事:

  1. 冷启动慢:第一次跑 dev server 要花很久
  2. 热更新慢:改一行代码,重建/刷新耗时

你可以把它理解成:

  • 冷启动是“把工程变成可运行状态”
  • 热更新是“把变化增量反映到浏览器”

谁能把这两件事的成本压到最低,谁就显得快。


2. Webpack 的工作方式:打包优先(Bundle-first)

Webpack 的核心思想很朴素:

先把依赖图解析完,打包成 bundle,再给浏览器。

在开发模式下也是如此:

  • 你启动 Webpack dev server
  • 它会解析入口文件 → 把依赖图全跑一遍
  • 再把模块通过 loader/plugin 转换、合并、产出

优点:

  • 一致性强:开发/生产链路相似
  • 生态丰富:loader/plugin 世界巨大

代价:

  • 依赖图越大,冷启动越慢
  • 改动影响范围越大,更新越慢

Webpack 在这条路线上做了大量优化(缓存、增量编译、持久化缓存等),但它依然绕不开一个前提:

你需要先“打包”才能“开发”。


3. Vite 的核心:开发阶段不打包(Dev-time No-bundle)

Vite 的核心思想可以总结成一句话:

开发时尽量不做 bundle,让浏览器用原生 ESM 按需加载。

现代浏览器支持 ES Modules:

  • import 会触发网络请求
  • 浏览器可以按需加载模块

Vite 的开发服务器更像一个“模块服务商”:

  • 浏览器请求哪个模块
  • Vite 就只编译/转换哪个模块

这样一来:

  • 冷启动不需要全量打包
  • 热更新只影响被改动模块及其必要的依赖边界

这就是你感受到“快”的第一根骨头。


4. Vite 为什么能快:4 个关键机制

4.1 原生 ESM + 按需编译:只为你现在看的页面服务

在 Webpack 的世界里:

  • 入口一启动,整棵依赖树都得处理

在 Vite 的 dev 世界里:

  • 你打开哪个页面,就请求哪些模块
  • 没用到的模块不需要先处理

这会让大型项目的“第一次可用时间”明显变短。

4.2 依赖预构建(pre-bundle):把第三方依赖变得“更适合浏览器”

现实问题是:

  • 你的源码通常是 ESM
  • 但 node_modules 里很多包是 CJS 或混合格式
  • 还有一些包有非常多小文件,浏览器会请求爆炸

Vite 会在首次启动时做一次 依赖预构建

  • 把第三方依赖用非常快的工具(通常是 esbuild)处理成更适合浏览器加载的形态
  • 合并/优化依赖的模块请求数量

你可以把它理解成:

源码按需,依赖先打包。

这也是 Vite “既快又不崩”的关键平衡。

4.3 esbuild / SWC 的速度红利:JS 工具链的“引擎换代”

Vite 在 dev 环节会尽量使用更快的编译器:

  • esbuild(Go 写的)
  • 或 SWC(Rust 写的)

它们在 TS/JS 转换上通常比传统工具快很多(尤其是冷启动和大量文件场景)。

4.4 精准 HMR:热更新不是“重来”,而是“定位更新边界”

HMR 本质是:

  • 找到变更模块
  • 找到接受更新的边界
  • 在不刷新页面的情况下替换模块并保持状态

Vite 的模块图(module graph)更贴近浏览器的请求图,因此更新路径更短、更直接。


5. 生产构建:Vite 不是不打包,而是“把打包放到生产”

一个常见误解:

  • “Vite 不打包”

更准确的是:

  • Vite 开发时不打包
  • Vite 生产构建会打包(默认用 Rollup)

为什么生产必须打包?

  • 浏览器请求太多模块会慢(网络开销)
  • 需要代码分割策略(chunks)
  • 需要压缩、tree-shaking、资源处理、兼容性处理

所以 Vite 的哲学是:

dev 追求反馈速度,build 追求产物质量。


6. 那 Webpack 什么时候更合适?(别急着判死刑)

Webpack 依然非常强,尤其在这些场景:

  1. 超复杂的定制化构建链:大量自定义 loader/plugin、历史包袱重
  2. 成熟生态依赖:某些老插件/体系只在 Webpack 下稳定
  3. 需要极强的兼容策略:一些边界情况你更熟悉 Webpack 的解法

一句话:

  • 如果你项目是“历史巨轮”,Webpack 的确定性和生态很值钱。

7. 选择指南:别问“谁更快”,问“你最怕什么”

你可以用下面的决策表快速选:

  • 你最怕开发反馈慢(冷启动/HMR) → 倾向 Vite
  • 你最怕迁移风险/生态不兼容 → 倾向 Webpack
  • 你是 monorepo、依赖多、工具链现代 → 很多时候 Vite + pnpm 组合体验更好
  • 你团队对构建系统掌控力一般 → 越简单越好,Vite 往往更省心

8. 面试怎么讲得像懂行?

面试官问“为什么 Vite 快”,你可以这样答:

  1. Vite dev 基于原生 ESM,按需加载模块,不需要全量 bundle。
  2. 对第三方依赖会预构建(pre-bundle),减少请求开销并统一模块格式。
  3. dev 转换通常借助 esbuild/SWC 等更快的编译器。
  4. 生产阶段仍然需要打包(Rollup),dev 快不代表 build 就不做优化。

这套回答能明显区分“用过”和“理解过”。


总结

  • Webpack:bundle-first,生态成熟、可定制性强,但大项目冷启动/更新可能更重。
  • Vite:dev-time no-bundle,原生 ESM + 依赖预构建 + 更快编译器,让开发反馈更快。
  • 选择关键不是“谁更强”,而是你的项目与团队更需要“速度”还是“确定性”。

小明金句收尾:

Vite 让你快,不是因为它更神,而是因为它更懂“开发”和“生产”是两种不同的战争。