← 返回 构建与部署图解 目录
📦 前端打包全链路
Webpack 和 Vite 到底在干嘛?为什么 Vite 快?一页看懂
① 先搞懂:打包到底是干嘛的?
你写的代码浏览器看不懂,打包工具帮你翻译+整理成浏览器能直接用的文件。
.vue / .jsx / .scss / TypeScript → 翻译成 → .js / .css / .png(浏览器认的格式)
你写了一堆 .vue、.scss、.ts 文件,还用了 import 互相引用。但浏览器只认 HTML/CSS/JS 三件套,不认识 .vue 是啥。
打包工具就是翻译官+搬运工:把你写的各种格式的源码,翻译成浏览器能直接跑的 JS/CSS/图片,还要把零散的文件合并、压缩、优化,最后放到 dist/ 目录里,就能部署上线了。
目前主流打包工具有两个:
📦
Webpack
老牌选手(2012年),生态最成熟。先把所有文件打包成一个 bundle,再启动。
特点:稳,但启动慢
⚡
Vite
新秀(2020年),Vue 作者出品。不打包,浏览器要什么才编译什么。
特点:快,秒级启动
② Webpack 怎么打包的?
Webpack = 工厂流水线:开门营业前,要把所有菜提前做好摆好。
从入口文件开始,顺着 import 一路找下去,把所有用到的文件都找出来 → 用 loader 翻译 → 用 plugin 加工 → 最后打包成一个 bundle.js。
问题:项目越大,要找的文件越多,启动越慢(几十秒到几分钟)。
Webpack 打包 5 步:入口 → 依赖收集 → Loader 翻译 → Plugin 加工 → 输出
Loader 和 Plugin 有啥区别?
| Loader(加载器) | Plugin(插件) |
| 干嘛的 | 翻译文件内容 | 在整个过程中做额外的事 |
| 举例 | vue-loader 把 .vue 变成 JS babel-loader 把 ES6 变成 ES5 sass-loader 把 .scss 变成 CSS | HtmlWebpackPlugin 生成 HTML MiniCssExtractPlugin 抽取 CSS CompressionWebpackPlugin 压缩 |
| 一句话 | "怎么翻译文件" | "还能干什么别的事" |
面试常问"loader 和 plugin 区别"——记住一句话:loader 管翻译文件,plugin 管扩展功能。
③ Vite 怎么工作的?
Vite = 快闪店 / 回转寿司:开门就营业,客人点什么现做什么。
不提前打包!浏览器请求哪个文件,Vite 就现场编译哪个文件返回。
结果:启动只要不到 1 秒,不管项目多大都这么快。
Vite 工作流程:预构建依赖 → 秒级启动 → 按需编译(不打包)
④ 为什么 Vite 这么快?(面试必问)
三个原因(面试标准答案):
🚀
① esbuild 预构建
用 Go 语言写的 esbuild 编译第三方库,比 babel(JS写的)快 10~100倍。Go 是编译型语言,天生比 JS 快,还用多核并行。
🌐
② Native ESM
开发时不打包!利用浏览器原生的 ES Modules 能力,浏览器请求哪个文件就编译哪个,直接返回 ESM 格式的 JS。
🎯
③ 按需编译
只编译当前页面用到的文件。500 页面的后台系统,打开登录页只编译登录页那 10 个文件,剩下 490 个不碰。
注意区分:Vite 开发时不打包(用 esbuild + 浏览器 ESM),但生产构建时还是要打包的!生产用 Rollup 打包(Tree Shaking 更彻底、产物更小)。
开发追求快 → esbuild;生产追求优 → Rollup。两个工具各司其职。
⑤ 几个常见概念(一句话搞懂)
🌳
Tree Shaking(摇树)
打包时自动删掉没被用到的代码。你 import 了 lodash 但只用了 debounce,其他函数不会打包进去。
前提:必须用 ES Module(import/export),CommonJS(require)不行。
✂️
Code Splitting(代码分割)
把一个大 bundle 拆成多个小 chunk,按需加载。首屏只加载首页代码,其他页面用到才加载。常见方式:动态 import()。
🔥
HMR(热更新)
改了代码不刷新整个页面,只替换改的那个模块,保留页面状态(表单输入、滚动位置)。
Webpack 要重新编译模块链(慢);Vite 只编译那一个文件(快,恒定 50ms)。
📦
Chunk(代码块)
多个模块打包在一起就是一个 chunk。比如 vendor.js(第三方库)+ main.js(你的代码)+ home.js(首页懒加载)。
HMR 热更新原理(简单版)
传统刷新(F5)= 脱光重穿:全身衣服都脱了再穿,身上带的东西(页面状态)全丢了。
HMR = 只换一件:坐着不动,只换那一件要换的衬衫,其他不碰,状态全保留。
流程:文件改动 → 服务器检测到 → 通过 WebSocket 通知浏览器 → 浏览器拉取新代码 → 替换旧模块(不刷新页面)。
Vite HMR 为什么更快:Webpack 要重新编译受影响的模块链(改一个文件,它依赖的模块也要重新打包);Vite 只编译改的那一个文件,不管项目多大,永远 50ms 以内。
⑥ 面试速答(背这些就够)
Vite 为什么比 Webpack 快?(最高频)
三个原因:
1. esbuild 预构建:用 Go 写的 esbuild 编译依赖,比 babel 快 10~100 倍
2. Native ESM:开发时不打包,利用浏览器原生 ESM,请求哪个文件才编译哪个
3. 按需编译:只编译当前页面用到的模块,不编译没访问的页面
结果:冷启动 <1s(和项目大小无关),HMR <50ms(恒定)
Webpack 打包流程是什么?
5 步:① 从 entry 入口开始 → ② 顺着 import 递归找所有依赖 → ③ 用 loader 翻译非 JS 文件 → ④ 用 plugin 做额外处理 → ⑤ 输出到 dist 目录。
本质就是"从入口出发,递归收集依赖,用 loader 转换,用 plugin 扩展,最后打包输出"。
loader 和 plugin 的区别?
loader 是"翻译器":处理文件内容,把非 JS 文件(.vue/.scss/.ts)转成 JS。比如 babel-loader 把 ES6 转 ES5。
plugin 是"扩展器":介入整个构建过程,做 loader 做不了的事。比如生成 HTML、压缩代码、抽取 CSS。
一句话:loader 管"怎么翻译文件",plugin 管"还能干什么别的事"。
HMR 热更新原理?Vite 和 Webpack 的 HMR 区别?
HMR 原理:文件改动 → 服务器重新编译 → WebSocket 通知浏览器 → 浏览器拉取新代码 → 替换旧模块(不刷新页面,保留状态)。
区别:Webpack HMR 要重新编译受影响的模块链(慢,随项目增长);Vite HMR 只编译改的那一个文件(快,恒定 50ms)。
Vite 生产构建为什么用 Rollup 不用 esbuild?
esbuild 快但代码分割和 CSS 处理不成熟;Rollup 慢一点但Tree Shaking 更彻底、产物体积更小。
开发追求快 → esbuild;生产追求优 → Rollup。各司其职。
什么是 Tree Shaking?
摇树优化:打包时自动删掉没被用到的代码。你 import 了一个库的 4 个函数但只用了 2 个,另外 2 个不会出现在最终产物里。
前提:必须用 ES Module(import/export 是静态的,编译时能确定)。CommonJS(require)是动态的,不能 Tree Shaking。
什么是 Code Splitting?
代码分割:把一个大 bundle 拆成多个小 chunk,按需加载,减小首屏体积。
最常见方式:const Foo = () => import('./Foo.vue'),用到才加载(懒加载路由就是这个原理)。
好处:首屏只加载当前页面代码,其他页面用到才加载,首屏更快。
新项目选 Vite 还是 Webpack?
新项目无脑选 Vite。Vue 3 / React 18 官方脚手架都默认 Vite,开发体验碾压,生态已经够用。
Webpack 仍不可替代的场景:Module Federation(微前端模块联邦)、重度依赖 Webpack 专属插件的老项目。
速记口诀:
• Vite 快三宝:esbuild + Native ESM + 按需编译
• Webpack 五步:入口 → 依赖收集 → loader 翻译 → plugin 加工 → 输出
• loader 翻译文件,plugin 扩展功能
• HMR:Webpack 编译模块链(慢),Vite 只编译一个文件(快)
• 开发用 esbuild(快),生产用 Rollup(优)