首先,基本礼仪,祝在这的各位国庆节快乐呐!(*σ´∀`)σ
别问本咕为啥更新这东西,问就是因为没活整了,但是咕了吧又不好(不是
1. 关于开发模式和生产模式
在上一篇文章中,咱确确实实提到过有个东西叫做 mode
,这东西有俩值,一个是 development
(开发模式),另一个是 production
(生产模式)。
在开发以及调试阶段,我们会使用开发模式,开发时我们只关心代码能运行,能在浏览器上有效果即可,至于代码被编译成什么样子,我们并不需要知道。
同理,在代码即将上线时,我们会使用生产模式,将代码打包到最佳的状态,以使用户获得最好的体验。
那么这个时候,开发模式和生产模式之间就有明显的配置上的区别了,因此不能像以前一样共用一个 webpack.config.js
了,而是分开使用两个配置文件,分别为 webpack.dev.js
和 webpack.prod.js
来进行配置。
于是我们在 config
文件夹有以下俩文件了
webpack.dev.js :
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
module.exports = {
// ...
mode: "development"
}
webpack.prod.js :
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
module.exports = {
// ...
mode: "production"
}
同理,package.json
里的命令也该更换了:
"start": "npx webpack --config ./config/webpack.dev.js",
"build": "npx webpack --config ./config/webpack.prod.js"

这样我们就可以用 npm start
运行开发模式,用 npm run build
运行生产模式了!
2. 开发服务器 | DevServer
各位应该注意到一个问题:我们真正需要把打包好的代码输出到某目录的话,只是在生产模式才需要。
而如果在开发环境将打包好的代码输出到对应文件夹的话,会拖慢打包速度,我们开发起来一次一次在浏览器刷新也不方便。
于是,就有了这个东西 —— Webpack DevServer,开发服务器!
顾名思义,开发服务器就是让你在开发时用的,它不会在本地产生输出,而是把打包的文件放在内存里,而且拥有类似 LiveServer 插件一样,可以通过 localhost 使浏览器实时效果预览打包后效果的功能。
首先安装 webpack-dev-server
npm i webpack-dev-server -D
接下来就在 webpack.dev.js
的最后添加这一项:
devServer: {
host: "localhost" // 主机名,如果是 0.0.0.0 则可以被外部访问
port: 3000, // devServer 的端口号
compress: false // 是否压缩代码
}
而 package.json
中的开发模式命令就应该改成
"start": "npx webpack serve --config ./config/webpack.dev.js"
欸,然后运行,当提示 “Webpack xxx compiled successfully in xxx ms” 后,打开 http://localhost:3000
(或你自己指定的端口号)


由于 Webpack 的 DevServer 能够实时更新已经修改的内容,所以只要不重名,不要给 CSS 或 JS 文件名带上 hash 值方便调试!
3. 怎么打包图片 / 字体等资源?
在 Webpack 5 以前,我们还需要安装 file-loader
,然而现在 Webpack 5 帮我们内置了这个东西。所以我们如果要添文件,直接在 loader
里面写就是了咕!
要有在 CSS 或 JS 中引用,才能打包这个文件呐!
{
test: /\.(jpg|png|woff2)$/, // 说明此 file-loader 作用于 jpg/png/woff2 文件上
type: 'asset',
generator: {
filename: './static/res/[name].[ext]' // 输出路径
}
}

4. 简单了解 chunk
从官方的角度说,chunk 实际是 “一堆 module
的集合”,也就是 module
把源代码打包后相应的产物。通常,我们指定一个 entry
,Webpack 就会顺着这个入口把所有资源打包,最后生成的就是 chunk。
换言之,我们知道代码最终会生成出一个 CSS 文件和一个 JS 文件,其实它们就是一个 chunk。

5. 如何一次性打包多个 HTML 文件并应用不同的样式?
上面我们提到了,Webpack 会顺着 entry
里面打包,然后形成 chunk 并输出。
那么家人们,如果我有多个 entry
,那就可能会产出多条打包路径,一条路径就会形成一个 chunk,这不就实现了嘛?。
(是的,确实可以有多个 entry
那么就可以举栗子了 (*˘︶˘*)。我们写两个页面,创建两个入口文件,写两个不同的样式并分别在两个入口中引入。
首先在配置文件中引入两个 entry
entry: {
1: "./src/1.js",
2: "./src/2.js"
}
然后写俩入口:
// 1.js
import "./style/1.less"
// 1.less
// body { background: yellow; }
// * { color: #000; }
// 2.js
import "./style/2.less"
// 2.less
// body { background: green; }
// * { color: #fff; }
然后回到配置文件,因为有俩 HTML,所以需要 new
俩 HtmlWebpackPlugin
。
// 1
new HtmlWebpackPlugin({
template: path.resolve(__dirname, "../public/1.html"), // 源文件
filename: "1.html", // 输出的文件
chunks: ["1"] // 使用的 chunk
}),
// 2
new HtmlWebpackPlugin({
template: path.resolve(__dirname, "../public/2.html"), // 源文件
filename: "2.html", // 输出的文件
chunks: ["2"] // 使用的 chunk
}),
6. 资源映射 | SourceMap
在开发过程中出现 bug 的时候,我们需要定位这个 bug 到底在哪里。
然而被打包成 chunk 之后,bug 出现在哪里反而不好找,因为控制台报错总是显示 chunk 中某一行。
这个时候我们就需要一个索引,能够显示源码及其路径,而资源映射呢就是专职做这玩意儿的。
而我们只需要像添加 devServer
一样,在 module.exports
中找空,卡进去(?)
devtool: "(SourceMap 的形式)"
SourceMap 有二十多种形式,咕咕喜欢并且建议各位在开发模式下用 cheap-module-source-map ,而在生产模式下用 source-map。


当然有更多想法?的话你也可以自行搜索关于 SourceMap 的知识!
7. 生产模式小妙招(?)
在打包过程中,各位(包括本咕)肯定会遇到 dist
文件夹杂乱(即新旧文件一起存放)的情况。
那么我们要让 Webpack 先清理过去已经生成的文件,再输出文件。其实,只需要在 output
项中添加:
clean: true
8. 理清 plugin 和 loader 的关系
最最最简单的理解,就是 loader
负责编译文件,而 plugin
负责把编译好的输出出来。比如输出 CSS 和 HTML 文件,就是 loader
先处理,然后通过 plugin
打包输出。
以下具体内容摘自 https://zhuanlan.zhihu.com/p/254898140,理解性差的同学散了吧?
loader
即为文件加载器,操作的是文件,将文件 A 通过 loader
转换成文件 B,是一个单纯的文件转化过程。 plugin
即为插件,是一个扩展器,丰富 Webpack 本身,增强功能 ,针对的是在 loader
结束之后,Webpack 打包的整个过程,他并不直接操作文件,而是基于事件机制工作,监听 Webpack 打包过程中的某些节点,执行广泛的任务。
(完结撒花🎉🎉🎉)
各位大佬们要是有疑问的话,欢迎评论区讨论的说!
(附赠从隔壁白嫖的 Webpack 5 从小白到大神 VuePress 版课件,要想深究的话点就是咯~)