「这是我参与11月更文挑战的第12天,活动详情查看:2021最后一次更文挑战」
前面我们讲了 file-loader 和 url-loader 的使用,url-loader 可以替换掉 file-loader,在开发中,如果我们想把所有图片全部做单独的打包,可以选择使用 file-loader,而如果想把图片转成 base64 编码,就可以选择使用 url-loader。
下面,我们再来介绍一个 Webpack5 中的新功能:Asset Module。
我们当前项目中使用的 webpack 版本是 Webpack5,在 Webpack5 之前,加载资源文件(字体、图标等等)需要使用一些 loader,比如 raw-loader(现在用的不多,在特殊场景会用到)、url-loader、file-loader;而从 Webpack5 开始,我们可以直接使用资源模块类型(asset modules type),来替代前面的这些 loader。资源模块类型(asset modules type)通过添加 4 种新的模块类型,来替换所有这些 loader:
asset/resource发送一个单独的文件并导出URL。之前通过使用file-loader实现;asset/inline导出一个资源的data URI,之前通过使用url-loader实现;asset/source导出资源的源代码,之前通过使用raw-loader实现;asset在导出一个data URI和发送一个单独的文件之间自动选择。之前通过使用url-loader并配置资源体积限制实现;
因此,前面我们配置的 file-loader 或 url-loader 现在就可以替换成 Asset Modules 了,我们来修改 webpack.config.js 中的内容:
...
module.exports = {
...
module: {
rules: [
{
test: /\.css$/,
use: [
'style-loader',
'css-loader',
'postcss-loader'
]
},
{
test: /\.less$/i,
use: [
'style-loader',
'css-loader',
'less-loader'
]
},
{
test: /\.(jpe?g|png|gif|svg)$/,
type: "asset/resource" // 使用类型为 asset/resource 的 Asset Modules
}
]
}
}
我们在规则对象中设置 type: "asset/resource",就相当于使用了 file-loader,即将匹配到的所有图片文件都进行单独的打包。修改完配置后,我们先删除项目中的 ./build 文件夹,再来打包看下效果:
当然,我们最常用的可能是 asset 类型的 Asset Modules,所以我们再来修改 webpack.config.js 中的内容:
...
module.exports = {
...
module: {
rules: [
...
{
test: /\.(jpe?g|png|gif|svg)$/,
type: "asset", // 使用类型为 asset 的 Asset Modules,
parser: {
dataUrlCondition: {
maxSize: 100 * 1024 // 小于 100kb 的文件将会被当作 asset/inline 类型对待,即会进行 base64 编码;否则会被当作 asset/resource 类型对待,即会被做单独的打包
}
}
}
]
}
}
修改完配置后,我们先删除项目中的 ./build 文件夹,再来打包看下效果:
现在,一张大小为 148kb 的图片被单独打包了,而另一张大小为 56kb(小于 100kb)的图片则被编码成了 base64 编码格式打包进了 bundle.js 中。
如果只是配置了
type: 'asset',而没有手动配置Rule.parser.dataUrlCondition.maxSize选项,那么webpack会默认将大小在8kb以下(不包括8kb)的文件作为asset/inline类型对待,否则作为asset/resource类型对待。具体内容可以阅读官方文档:
如果想把单独打包的图片文件放在一个 img 文件夹下,我们可以这样做:
...
module.exports = {
...
module: {
rules: [
...
{
test: /\.(jpe?g|png|gif|svg)$/,
type: "asset",
parser: {
dataUrlCondition: {
maxSize: 100 * 1024
}
},
generator: {
filename: 'img/[name]_[hash:6][ext]' // 注意,这里 [ext] 获取到的扩展名前面已经带了 . 号
}
}
]
}
}
修改完配置后,我们先删除项目中的 ./build 文件夹,再来打包看下效果:
你也可以这样配置(用得较少):
const path = require('path');
module.exports = {
entry: './src/main.js',
output: {
path: path.resolve(__dirname, './build'),
filename: 'bundle.js',
assetModuleFilename: 'img/[name]_[hash:6][ext]' // 指定 asset modules 的输出文件名
},
module: {
rules: [
...
{
test: /\.(jpe?g|png|gif|svg)$/,
type: 'asset',
parser: {
dataUrlCondition: {
maxSize: 100 * 1024
}
},
// generator: {
// filename: 'img/[name]_[hash:6][ext]'
// }
}
]
}
}
关于自定义
Asset Modules的Resource assets的输出文件名的具体内容可以查阅官方文档:
有了 Asset Modules 之后,我们以后就不需要再使用 file-loader 和 url-loader 了,甚至都不需要安装它们了,当然,前提是从 Webpack5 开始。
以上,就是关于 Webpack5 最新的打包资源的方式。