Webpack vs Vite
Webpack vs Vite
Breezli你是否曾被这些名词搞晕:打包工具、构建工具、Webpack、Vite,它们到底是干嘛的?为什么前端开发离不开它们?
前端为什么需要“打包”
当你开发一个网站时
你有巨量文件:几十个 .js
脚本、一堆 .css
样式、一些图片 .png
、字体 .woff
、甚至 .vue
或 .ts
文件
浏览器很“笨”:
- 它一次只能加载有限的文件(太多请求会慢)
- 它不认识
.vue
、.ts
或最新的 JS 语法(如import
),往往需要额外配置 - 它不知道文件之间的依赖关系(哪个 JS 需要先加载)
你想做优化:比如压缩代码体积、合并文件、给图片瘦身
现在市面上的构建工具就是来解决这些问题的
打包工具可以
- 指挥:从一个入口文件(比如
main.js
)开始,找出所有它需要的文件(依赖),再找出这些文件需要的文件,最后呈现一个巨大的依赖关系网 - 翻译:把浏览器看不懂的语言(如
.ts
,.vue
,.scss
, 新 JS 语法)转换成浏览器能懂的.js
和.css
- 打包:把处理好的文件,按照规则组合、压缩、优化,最终生成少数几个(甚至一个)高效的文件(如
stats.es.html
,index.js
,index.css
) - 搬运:把图片、字体等资源处理好,放到正确的位置。
最终目标:让浏览器加载更少的文件、加载更小的文件、加载浏览器能懂的文件,从而让网站加载更快、运行更稳
Webpack vs Vite
理解了打包工具的作用,现在来看看 Webpack 和 Vite 这两个打包工具的“工作流程”有什么根本不同
Webpack:“打包先行”
- 核心理念:优先完整打包
- 工作流程(开发阶段):
启动:你运行
npm run dev
大打包:Webpack 立刻开始分析你的整个项目,从
main.js
开始递归分析所有import/require
,画出巨大的 JSON 结构依赖图谱(包含所有文件路径、依赖关系、模块ID)// Webpack 生成依赖图谱 { "./src/main.js": { id: 1, dependencies: ["./src/Header.js", "./src/utils.js"] }, "./src/Header.js": { id: 2, dependencies: ["./src/assets/logo.svg", "./src/Header.css"] } // ... 其他文件 }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
- 然后让 Loader 们翻译所有文件,最后把它们打包成一个或几个大文件 (`index.js`)
- > 这个过程通常很慢,尤其项目很大时
- **启动服务器**:打包完成后,启动一个开发服务器
- **浏览器加载**:浏览器访问页面,加载的是打包好的大文件
- **修改代码**:你改了一个文件(比如 `Button.vue`)
- **重新打包**:Webpack 发现文件变了,它会重新分析依赖(可能不需要全部分析,有缓存),然后重新打包受影响的部分,生成新的 `index.js`
- **热更新 (HMR)**:Webpack 通过技术手段,告诉浏览器`Button.js` 那块代码变了,浏览器就只更新那局部,不用刷新整个页面(体验更好)
- **优点**:
- **成熟稳定**:久经考验,**生态极其丰富,什么场景几乎都有解决方案**
- **功能强大**:能处理非常复杂的项目结构和需求
- **痛点**:
- **启动慢(冷启动)**:项目越大,第一次启动时那个“大打包”过程就越慢。等几十秒是常事
- **更新有时也慢**:虽然 HMR 很快,但如果改动影响了核心依赖,可能还是需要较长时间重建
- **配置复杂**:想用好要学不少配置知识,新手容易b溃
### Vite:“按需编译”
- **核心理念**:**不完全打包,按需服务**
- **工作流程(开发阶段)**:
- **启动**:你运行 `npm run dev`
- **秒开服务器**:Vite 瞬间启动一个开发服务器(几乎不用等),它**完全不打包**你的源码
- **浏览器请求**:Vite 返回的是一个**极简的 HTML**,**里面用** **`<script type="module">`** **加载你的** **`main.js`**,这也是浏览器请求的`main.js`
- > 这是关键!现代浏览器原生支持 `type="module"`,意味着浏览器自己就能处理 `import` 语句
- **按需请求**:浏览器执行 `main.js`,遇到 `import { Button } from './components/Button.js'`,它就向 Vite 服务器请求 `Button.js`
- ```YAML
// 浏览器真实请求序列
1. GET /src/main.js
2. GET /src/Header.js?import // Vite 添加?import标识
3. GET /src/assets/logo.svg?import
4. GET /src/Header.css?import按需编译:Vite 服务器收到请求
Button.js
时,才临时把它(以及它可能引入的依赖)从原始语言(如.vue
,.ts
)快速编译成浏览器能懂的 JS,然后返回给浏览器。所以说,你当前没访问的代码,Vite 根本不管修改代码:你改了一个文件(比如
Button.vue
)极速热更新:Vite 瞬间知道哪个文件变了。它只重新编译这个文件(速度极快),然后通过极其高效的 HMR 告诉浏览器:“只更新
Button.vue
对应的部分” ,非常非常快
- 优点:
- 启动飞快:项目再大,启动也是秒开(几百毫秒)
- 更新飞快:改哪里编译哪里,HMR 快到离谱
- 开箱即用:对现代技术(ESM, TypeScript, JSX, Vue, React)支持极好,配置简单很多
- 痛点:
- 生态相对年轻:虽然发展迅猛,但一些非常特殊或老旧的场景,可能没有 Webpack 那么成熟的解决方案
- 对旧浏览器支持弱:重度依赖浏览器原生 ESM,对 IE 等老古董不太友好(生产环境通过打包可以解决)
流程总结:
Webpack:
启动+打包慢
→启动服务器
→浏览器加载大包
→改代码
→重新打包慢
→HMR 更新
Vite:
启动超快
→启动服务器
→浏览器加载入口
→按需请求
→按需编译快
→改代码
→按需编译超快
→HMR 更新超快
性能对比
体验指标 | Webpack 开发模式 | Vite 开发模式 | Vite 优势 |
---|---|---|---|
冷启动 | 必须等整个项目打包完才能启动服务器,项目越大越慢 | 无需等待打包,瞬间启动服务器,项目大小带来的影响极小 | 快 10 倍甚至 100 倍 |
热更新 (HMR) | 较慢,需要重新打包受影响的部分,改动核心文件时可能 | 极快,只编译单个改动的文件 | 快得多 |
内存占用 | 较高,需要维护整个项目的依赖关系图和打包状态 | 很低,按需加载,只编译当前需要的文件 | 更省资源 |
生产构建 | 成熟稳定,优化能力强。速度取决于配置和项目复杂度。 | 使用 Rollup 打包,同样成熟高效,Tree Shaking 优秀 | 两者相当,Vite(Rollup) 可能略优 |
插件生态
打包工具的强大功能,很多是靠“插件”扩展的
Webpack 插件生态:
- 特点:存在时间最长,插件数量最多,覆盖场景最广,从处理各种文件类型,到代码压缩、图片优化、性能分析、特殊部署,几乎没有找不到的插件
- 优势:功能极其全面,适合处理极其复杂、特殊的需求
- 缺点:配置相对复杂,学习成本高,插件开发也比较难
- 代表插件:
html-webpack-plugin
(生成HTML文件),mini-css-extract-plugin
(提取CSS),clean-webpack-plugin
(清理旧文件),webpack-bundle-analyzer
(分析包大小)
Vite 插件生态:
- 特点:生态发展非常快,核心优势是 API 设计更现代、简洁,很多插件在开发模式下就能发挥很好作用(如调试、Mock 数据)。可直接兼容大量 Rollup 插件,可利用 Rollup 的成熟生态
- 优势:配置通常更简单,插件开发更容易上手,与 Vite 的按需编译、原生 ESM 特性结合紧密
- 缺点:不如 Webpack 的插件成熟
- 代表插件:
@vitejs/plugin-vue
(支持Vue单文件组件),@vitejs/plugin-react
(支持React),vite-plugin-inspect
(可视化调试依赖和转换),,unplugin-auto-import
(自动引入API),vite-plugin-pwa
(支持PWA)
插件开发实战
Webpack 插件
1 | // webpack-custom-plugin.js |
Vite/Rollup 插件
1 | // vite-custom-plugin.js |