⚡ 为什么 Vite 能取代 Webpack
核心结论(TL;DR)
Vite 撬动 Webpack 的支点,是一次教科书级的第一性原理操作:它没有去”把打包做得更快”,而是重新质疑了一个被默认了十年的前提——“开发时为什么要打包?” 当浏览器原生支持了 ES-Modules,这个前提就不再成立。Vite 用 no-bundle dev(原生 ESM 按需编译)+ esbuild 预构建 + Rollup 生产打包 的组合,把开发服务器冷启动从”O(n) 几十秒”降到”O(1) 几百毫秒”。它取胜的核心不是功能,而是开发体验(DX)本身已成为第一竞争力。但要承认:它早期存在 dev/prod 双引擎不一致 的隐忧,且超大型/深度定制场景 Webpack 仍有优势——而 Rolldown(Rust 统一引擎)正是来收口这个问题的。
一、问题背景:争议是什么
Webpack 统治了整整十年,它的生态护城河深不见底:所有脚手架、教程、插件都基于它。按常理,这种被网络效应锁定的霸主不可能被快速取代。
但 2020 年 Vite(尤雨溪)发布后,只用了两三年,就成了新项目的默认选择:Vue 全面转向、SvelteKit/Astro/Nuxt/Solid 采用、Vitest 兴起、连 React 生态也大量迁移。
争议在于:一个生态锁定如此之深的霸主,凭什么被这么快撬动? 上一篇我们论证过”打破生态锁定不能靠渐进改良,只能靠范式革命”。Vite 正是那场范式革命——而它的武器,是一个简单到近乎”作弊”的发问。
二、关键原因拆解
原因 1:第一性原理 —— “开发时为什么要打包?”
这是整个故事的灵魂。Webpack 慢的根本原因不是实现,而是范式:
Webpack 的范式枷锁(bundle-based dev)
Webpack 即使在开发模式下,也必须先把整个应用的依赖图打包成 bundle,服务器才能启动。这意味着:
- 冷启动时间 ∝ 项目模块总数 = O(n)
- 项目越大,启动越慢(大项目几十秒到几分钟)
- 你改一行代码想看效果,却要等一个”全量构建”的副产物
人们诟病了十年,但默认了”开发时必须打包”这个前提,只在前提之内优化(缓存、多进程、DLL……)。
Vite 做的事是:跳出前提,直接问”这个前提还成立吗?”
答案是:不成立了。 因为现代浏览器原生支持了 ES-Modules(<script type="module">)。既然浏览器自己就能处理 import,开发时根本不需要把模块打包在一起——可以让浏览器直接请求模块,服务器按需编译被请求的那个模块。
Webpack(bundle-based dev):
启动 = 打包全部 n 个模块 → 才能服务 ……… O(n),随项目增大而恶化
Vite(no-bundle dev):
启动 = 起一个 ESM dev server(几乎瞬间) ……… O(1)
浏览器请求 main.js → import './App' → Vite 实时编译这一个文件返回
(只编译"屏幕上真正用到的"模块,而非全部)
这是从 O(n) 到 O(1) 的复杂度跃迁,不是常数级优化。质变来自重新提问,而非更努力地回答旧问题。
原因 2:esbuild 预构建 —— 用 Go 解决 ESM 的两个工程问题
纯 no-bundle 有两个现实障碍,Vite 用 esbuild(Go 编写) 巧妙化解:
- 第三方依赖的模块数量爆炸:像
lodash-es这种包有几百个内部模块,如果都用原生 ESM 按需请求,浏览器会发起几百个 HTTP 请求,反而变慢。Vite 用 esbuild 把这类依赖预打包成单个 ESM 模块(依赖预构建,pre-bundling),只此一次。 - CommonJS / UMD 包不是 ESM:很多老包不是 ESM,浏览器不认。esbuild 在预构建时把它们转成 ESM。
esbuild 用 Go 写,比 Babel(JS 写)快 10–100 倍,所以这步”预构建”几乎无感。
关键设计:区分"业务代码"和"依赖"
Vite 的洞察是:业务代码经常变(需要按需即时编译),而依赖几乎不变(适合一次性预打包并强缓存)。它用两种策略分治:
- 依赖 → esbuild 预构建 + HTTP 强缓存(
max-age长缓存)- 业务代码 → 原生 ESM 按需编译(改哪个编译哪个) 这个”按变化频率分治”的设计,是它又快又稳的关键。
原因 3:HMR 的速度也是 O(1)
Webpack 的 HMR 在大项目里会变慢,因为它要在依赖图里计算受影响的模块边界。Vite 的 HMR 基于原生 ESM:改一个文件,只让浏览器重新请求那一个模块(及其 HMR 边界),与项目规模基本无关——改完即见,几乎无延迟。
| 维度 | Webpack | Vite |
|---|---|---|
| 冷启动复杂度 | O(n)(打包全量) | O(1)(起 ESM server) |
| 启动时间(大项目) | 几十秒~几分钟 | 几百毫秒~几秒 |
| HMR 速度 | 随规模变慢 | 基本恒定,即时 |
| 依赖处理 | 打包进 bundle | esbuild 预构建 + 缓存 |
| 编译范围 | 全量 | 按需(只编译用到的) |
原因 4:DX 已成为第一竞争力 —— “秒级反馈”是不可逆的体验升级
这是 Vite 能快速扩散的社会学原因。在 工程化时代,框架的胜负已分,开发体验(DX)成了新战场。
“等构建”是对心流(flow)的持续打断。一旦开发者体验过 Vite 的”保存即见效”,再回到 Webpack 的”等几十秒”会生理性难受。这种体验落差口口相传,扩散速度极快——DX 的改善是单向阀,体验过更好的就回不去了。
二阶效应:DX 决定了工具的传播速度
性能数据是抽象的,但”等待的痛苦”是切身的。Vite 把一个抽象的工程指标(冷启动时间)转化成了每个开发者每天切身感受几十次的体验差。这让它的传播不靠论文、不靠论证,而靠身体记忆——这是最强的病毒式扩散动力。
原因 5:生态策略 —— 从 Vue 背书到框架无关
Vite 没有重蹈”绑死一个框架”的覆辙,而是走了一条聪明的扩张路径:
尤雨溪 + Vue 背书(可信的起点)
→ 设计成框架无关(plugin 体系,React/Svelte/Solid 都能用)
→ 各大元框架采用:SvelteKit / Astro / Nuxt3 / Qwik / Remix(后期)
→ Vitest(测试)复用 Vite 管线,扩展到测试领域
→ 成为"新一代前端基础设施"的默认底座
它复用了 Rollup 作为生产构建器(成熟、ESM 优先、tree-shaking 优秀),复用 esbuild 做转译,站在巨人的肩膀上而非重造轮子。这让它既快又稳,生态接入成本低。
三、反方 / 常见误解
Vite 不是没有代价的银弹
误解 1:“Vite 全面比 Webpack 快/好。” 不准确。Vite 快的是开发模式。生产构建走 Rollup,对超大型项目不一定比优化过的 Webpack 快。而 Webpack 的 Module Federation(微前端)、对非标准/复杂资源管线的处理、海量成熟 plugin,在深度定制场景仍有优势。
误解 2:“no-bundle 没有缺点。” 早期有真实痛点:dev 与 prod 的不一致。Vite 开发用原生 ESM + esbuild,生产用 Rollup——两套引擎,行为可能有微妙差异(“dev 正常 prod 出错”);首次加载未预构建的大量小模块时,瀑布式请求也可能慢。这是它的”双引擎不一致”原罪。
误解 3:“esbuild 那么快,为什么生产不用 esbuild?” 因为 esbuild 的代码分割和 tree-shaking 成熟度当时不如 Rollup,生产构建对产物质量要求更高,所以 Vite 选择”dev 用 esbuild 求快,prod 用 Rollup 求稳”。这恰恰是上面”双引擎”问题的根源。
误解 4:“Vite 已经终局了。” 没有。dev/prod 双引擎的不一致是悬而未决的架构问题。Rolldown(用 Rust 重写、兼容 Rollup API 的统一打包器)正是 Vite 团队为了用同一个引擎统一 dev 和 prod而做的下一步——这说明 Vite 自己也认为当前架构是过渡态。范式革命仍在继续。
四、本质洞察 / 元规律
撬动霸主的支点,不是"更努力地优化",而是"重新质疑被默认的前提"
规律 1:范式革命来自第一性原理,而非渐进优化。 所有人都在”如何让打包更快”的框架内努力(缓存、并行、增量),Vite 跳出来问”为什么要打包”。当一个底层条件变了(浏览器原生支持 ESM),旧前提的失效就打开了 O(n)→O(1) 的质变空间。最强的优化,是发现某个步骤根本不必存在。 这与 pnpm 重新质疑”为什么要复制 node_modules” 是同一种思维。
规律 2:外部条件的变化,是范式革命的真正触发器。 Vite 不是凭空天才,它是踩在了”浏览器普及原生 ESM”这个外部条件成熟的拐点上。同样的想法在 2015 年(浏览器不支持 ESM)无法实现。好点子需要等待使能条件(enabling condition)成熟——时机和洞察同等重要。这呼应了 React 踩中范式拐点 的规律。
规律 3:体验是单向阀,DX 改善具有不可逆的扩散力。 当一项改进直接作用于”每天感受几十次的切身体验”(而非抽象指标),它的传播就不靠论证,靠身体记忆。把工程指标翻译成体感差异,是打破生态锁定的最快路径——这是 Vite 能在三年内撬动十年霸主的社会学密码。
Webpack 的隐含前提:"开发时必须打包" ← 被默认了十年
│
浏览器原生支持 ESM(外部条件成熟)
│
Vite 第一性原理发问:"这个前提还成立吗?" → 不成立
│
no-bundle dev:O(n) ──► O(1) 的范式跃迁
│
DX 体感差(单向阀)→ 病毒式扩散 → 三年撬动十年霸主
五、结论
Vite 取代 Webpack(在新项目的默认地位上),核心是一次第一性原理驱动的范式革命:它不去优化打包,而是借助”浏览器原生 ESM”这个外部条件的成熟,取消了”开发时打包”这个步骤本身,实现了 O(n)→O(1) 的冷启动跃迁;再用 esbuild 预构建和 Rollup 生产构建补齐工程缺口;最终靠 DX 的不可逆体感差完成病毒式扩散。
但它远未终局:dev/prod 双引擎不一致是其架构原罪,Webpack 在超大型/深度定制场景仍有不可替代性,Rolldown(Rust 统一引擎)正在收口。最普适的洞察是:打败一个被生态锁定的霸主,武器从来不是”更努力”,而是”一个被重新提出的问题”。 当外部条件变化时,那些被默认的前提,就是下一场革命的支点。
🔗 相关:Vite | Webpack | Rollup | ES-Modules | Babel | Turbopack | 2018-2023 工程化时代 🔗 深度专题:为什么Webpack统治了十年 | 为什么pnpm解决了依赖问题 | 未来5到10年前端发展方向