Webpack 入门没那么难,摸鱼也能学会
上周五晚上九点半,我瘫在工位上刷 GitHub Trending,突然收到产品经理的消息:“小张啊,咱们下个版本要支持暗黑模式,顺便把首屏加载速度提升 30%。”
我差点把刚泡好的枸杞茶打翻——这需求来得比深圳的暴雨还突然。
我是谁?一个在深圳某腾讯系公司“躺平摸鱼但技术还在学”的前端,日常靠参加 Meetup 和啃文档续命。对动画和交互动效有点执念,但面对构建工具这种“基建活”,总想能拖就拖。可现实是:不搞懂 Webpack,连打包都跑不起来,更别说优化性能了。
于是,我被迫从“佛系”切换到“卷王模式”,花了三天时间啃完 Webpack 官方文档,边踩坑边记笔记。今天这篇,就是写给和我一样——嘴上说着“躺平”,身体却诚实地打开 VS Code 的你。
为啥非得用 Webpack?
别急着喷,“现在不是有 Vite 吗?” 是的,Vite 很香,但我司老项目还是 Webpack 4,升级成本高得能买十箱瑞幸。而且,理解 Webpack 能帮你真正搞懂“模块打包”到底在干啥——这不是为了应付面试,而是线上出问题时,你能快速定位是 loader 配错了还是 splitChunks 没配好。
去年双11前,我们首页白屏了整整 8 秒。运维甩锅给 CDN,测试说“本地跑得好好的”,最后发现是某个第三方 JS 库被重复打包了两次。当时我真的想砸电脑。后来加了 splitChunks + cacheGroups,首屏 JS 体积直接砍掉 40%。那一刻我悟了:前端工程化不是炫技,是保命技能。
从零跑通一个最简配置
先别被 webpack.config.js 吓到。其实核心就三要素:入口(entry)、出口(output)、加载器(loader)。我们一步步来。
1. 初始化项目
mkdir my-webpack-demo && cd my-webpack-demo
npm init -y
npm install webpack webpack-cli --save-dev
📌 小贴士:别忘了加
--save-dev,这玩意只在开发环境用,别往生产依赖里塞!
2. 写个最简配置
创建 webpack.config.js:
const path = require('path');
module.exports = {
entry: './src/index.js',
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist')
},
mode: 'development' // 别一上来就 production,debug 会疯
};
然后在 src/index.js 里写点 JavaScript:
// src/index.js
console.log('Hello, Webpack! 我终于不用手动拼 script 标签了');
运行:
npx webpack
搞定!dist/bundle.js 出现了。虽然它又大又丑,但至少能跑。
处理 CSS 和图片?靠 loader!
前端哪能只有 JS?我们得让 Webpack 认得 .css、.png 这些“外星文件”。
先装两个 loader:
npm install css-loader style-loader file-loader --save-dev
更新配置:
module.exports = {
// ...前面的 entry/output
module: {
rules: [
{
test: /\.css$/,
use: ['style-loader', 'css-loader']
// 注意顺序:从右往左执行!
},
{
test: /\.(png|jpg|gif)$/,
use: ['file-loader']
}
]
}
};
这时候你可能会问:“为啥 CSS 要两个 loader?”
css-loader:解析@import和url(),把 CSS 当成模块处理style-loader:把 CSS 插入<style>标签塞进 HTML
如果你用的是现代方案,可能还会看到 MiniCssExtractPlugin ——它能把 CSS 抽成单独文件,避免 JS 阻塞渲染。不过对新手来说,先用 style-loader 看效果更快,毕竟……我们还在摸鱼阶段嘛。
开发体验优化:热更新 + 本地服务器
每次改代码都要手动 npx webpack?那不得累死。Webpack Dev Server 来救场:
npm install webpack-dev-server --save-dev
在 package.json 加个脚本:
{
"scripts": {
"dev": "webpack serve --open"
}
}
再加点配置到 webpack.config.js:
module.exports = {
// ...
devServer: {
static: './dist',
hot: true // 启用热更新
}
};
现在跑 npm run dev,浏览器自动打开,改 CSS/JS 实时刷新——连 F5 都省了。这才是程序员该有的生活!
生产环境:压缩、分包、缓存
开发爽了,上线不能翻车。生产构建要干三件事:
- 压缩代码(Terser)
- 拆分公共代码(splitChunks)
- 加 hash 防缓存([contenthash])
Webpack 5 默认集成了 Terser,所以不用额外装插件。但分包得手动配:
module.exports = {
mode: 'production',
optimization: {
splitChunks: {
chunks: 'all',
cacheGroups: {
vendor: {
test: /[\\/]node_modules[\\/]/,
name: 'vendors',
chunks: 'all'
}
}
}
},
output: {
filename: '[name].[contenthash].js',
path: path.resolve(__dirname, 'dist')
}
};
这样打包后你会看到:
main.xxxx.js(你的业务代码)vendors.yyyy.js(所有 node_modules)
配合 HTML 引用,浏览器就能缓存 vendors 文件,用户下次访问只下小文件——首屏速度直接起飞。
常见坑 & 调试技巧
坑1:loader 顺序写反了
记住:use 数组是从右往左执行的。比如 ['style-loader', 'css-loader'],其实是先 css-loader 再 style-loader。写反了就报错。
坑2:路径别名没生效
想用 @/components 代替 ../../components?加 resolve.alias:
resolve: {
alias: {
'@': path.resolve(__dirname, 'src')
}
}
但注意:VS Code 可能不认识这个别名,得配 jsconfig.json 才有跳转提示。
调试神器:stats 分析
打包后想知道哪个包最大?加个参数:
npx webpack --profile --json > stats.json
然后扔到 webpack-bundle-analyzer 里,可视化分析体积。上次我发现一个 2MB 的图标库,其实只用了 3 个图标……立刻换成 SVG Sprite,JS 体积直降 60%。
写在最后:工程化不是目的,体验才是
说实话,Webpack 配置确实繁琐,文档也绕。但当你看到 Lighthouse 分数从 45 提到 85,用户反馈“页面秒开”,那种成就感,比摸鱼吃零食还爽。
我在 GitHub 上建了个最小可行 Webpack 模板,包含 CSS、图片、热更新、分包等基础能力。欢迎 fork,也欢迎提 issue 吐槽——毕竟,我们都是在 deadline 和 bug 中成长的打工人。
前端工程化的终点不是完美的配置,而是让用户感觉不到“工程”的存在。
而我,继续在深圳的晚风里,一边摸鱼,一边悄悄变强。
| 配置项 | 开发环境 | 生产环境 |
|---|---|---|
| mode | development | production |
| sourceMap | eval | false (或 hidden-source-map) |
| 压缩 | 无 | Terser 自动启用 |
| 缓存 | memory | filesystem / disk |
| 分包 | 关闭 | splitChunks 开启 |
注:别盲目照搬配置,根据项目规模调整。小项目分包反而增加 HTTP 请求,得不偿失。
好了,我的咖啡凉了,该去回产品经理消息了——“暗黑模式?没问题,下周上线!”(内心:先让我把 Webpack 升级完再说)

评论 0