Vite冷启动快是因为跳过依赖图构建、第三方预构建和业务代码全量编译;Webpack必须完成这三步,导致启动时间随项目规模线性增长。

冷启动速度差距的核心,不在“谁更快”,而在于“谁必须等”。Vite 的快,是跳过了 Webpack 必须走的那条路;Webpack 的慢,不是性能差,而是它根本不能跳过。
依赖图构建:Webpack 必须递归扫描,Vite 直接绕开
Webpack 启动前必须完成三件事:从入口开始解析 所有 import/require、递归收集全部模块、构建完整的依赖图。哪怕只改一行代码,冷启时也得重跑整个流程——项目越大,路径越深,耗时越长(20 秒起步很常见)。
Vite 根本不构建全局依赖图。它只起一个轻量 HTTP 服务,连源码目录都不扫描。浏览器请求 index.html → 加载 main.js → 遇到 import './App.vue' → 浏览器发请求 → Vite 拦截、即时编译单个 .vue 文件并返回。依赖关系由浏览器按需触发,服务端不预判、不预建。
第三方依赖处理:预构建 vs 全量打包
Webpack 对 node_modules 里的每个包都纳入同一套 loader/plugin 流程:解析 → 转译(如 Babel)→ 打包 → 压缩。哪怕一个纯 ESM 的 lodash-es,也要走完整 pipeline。
Vite 把第三方依赖单独拎出来,用 esbuild 做一次性的 预构建(pre-bundle):
- 只做一次,结果缓存到
node_modules/.vite - esbuild 编译速度比 Webpack 快 10–100 倍,且只转语法、不处理业务逻辑
- 输出统一为标准化 ESM 格式,浏览器可直接 import,无需二次处理
这意味着:Vite 启动时,第三方代码早已就绪;Webpack 启动时,这部分工作才刚开始。
业务代码加载:按需编译 vs 全量编译
Webpack 开发模式下,所有业务文件(.ts、.vue、.jsx)都在启动阶段被一次性读取、AST 解析、loader 处理、打包进内存 bundle。哪怕某个页面路由从未访问,代码也已编译完毕。
Vite 的业务代码完全惰性:
- 没被 import,就不加载、不编译
- 首次访问某路由,浏览器才请求对应模块,Vite 实时调用插件(如 @vitejs/plugin-vue)编译该文件
- 编译结果不落地、不缓存(开发阶段),仅返回给当前请求
所以 Vite 冷启动时间基本恒定(3–4 秒),和项目规模无关;Webpack 则随模块数线性增长,2000 个文件和 2 万个文件,启动时间可能差 5 倍。
HTTP 交互模型:ESM 原生驱动 vs Bundle 封装交付
Webpack dev server 提供的是打包后的 bundle.js,浏览器一次性下载执行。这要求服务端提前产出完整产物,本质仍是传统静态资源交付模型。
Vite 开发服务器模拟的是真实 ESM 环境:
- 入口是
index.html,里面写<script type="module" src="/src/main.ts"></script> - 浏览器按
import语句发起一个个 HTTP 请求(/src/App.vue、/node_modules/.vite/deps/react.js) - Vite 中间件逐个拦截、转换、返回,全程无 bundle 生成环节
这种设计把“构建”从启动前置动作,变成运行时按需服务——自然消除了冷启动瓶颈。


















