使用图片、字体等资源是当前 Web 应用中是非常常见的,在 Webpack 中可是使用import/require
语句像引用 JS 模块一样导入资源,当然这需要借助 loader,所以我简要总结一下如何处理资源。
在 Webpack4 及之前的版本中通常借助 Loader 如:file-loader
、url-loader
、raw-loader
等处理资源。
file-loader
将图像引用转换为 url 语句并生成相应图片文件.
// webpack.config.js
module.exports = {
// ...
module: {
rules: [{
test: /\.(png|jpg)$/,
use: ['file-loader']
}],
},
};
在上述配置中,经file-loader
处理完成后,原始图片会被重命名并复制到产物文件夹,同时在代码中插入图片 URL 地址,如下所示:
url-loader
有两种表现,对于小于阈值
limit
的图像直接转化为 base64 编码;大于阈值的图像则调用file-loader
进行加载。
module.exports = {
// ...
module: {
rules: [{
test: /\.(png|jpg)$/,
use: [{
loader: 'url-loader',
options: {
limit: 1024
}
}]
}],
},
};
在上述配置中,经url-loader
处理后,小于limit
的图片会被转译为 Base64 编码,如下所示:
raw-loader
不做任何转译,只是简单将文件内容复制到产物中,适用于 SVG 场景。
// webpack.config.js
module.exports = {
// ...
module: {
rules: [
{
test: /\.svg$/i,
use: ['raw-loader'],
},
],
},
};
经过raw-loader
处理后,SVG 资源会被直接复制成字符串形式:
除 raw-loader 外,我们还可以使用如下 Loader 加载 SVG 资源:
svg-inline-loader
:能够自动删除 SVG 图片中与显式无关的各种原信息,达到压缩效果;
svg-url-loader
:以 DataURL 方式导入 SVG 图片,相比于 Base64 更节省空间;
react-svg-loader
:导入 SVG 图片并自动转化为 React 组件形态,效果类似 @svgr/webpack;
上述file-loader
、url-loader
、raw-loader
被用于加载任意类型的多媒体或文本文件,使用频率极高,所以 Webpack5 直接内置了这些能力,开箱即可使用。
用法上,原本需要安装、导入 Loader,Webpack5 之后只需要通过module.rules.type
属性指定资源类型即可,对比来看:
file-loader
对标到type = "asset/resource"'
url-loader
对标到type = "asset"
或type = "asset/inline"
raw-loader
对标到type = "asset/source"
// webpack.config.js
module.exports = {
// ...
module: {
rules: [{
test: /\.(png|jpg)$/,
- use: ['file-loader']
+ type: 'asset/resource'
}],
},
};
默认情况下,asset/resource 生成的文件会以
[hash][ext][query]
方式重命名,可以通过output.assetModuleFilename
属性控制。
module.exports = {
// ...
module: {
rules: [{
test: /\.(png|jpg)$/,
- use: [{
- loader: 'url-loader',
- options: {
- limit: 1024
- }
- }]
+ type: "asset",
+ parser: {
+ dataUrlCondition: {
+ maxSize: 1024 // 1kb
+ }
+ }
}],
},
};
其中,
module.rules.parser.dataUrlCondition
用于限定文件大小阈值,对标 url-loader 的limit
属性。
module.exports = {
// ...
module: {
rules: [
{
test: /\.svg$/i,
- use: ['raw-loader']
+ type: "asset/source"
},
],
},
};
补充一下,引入
module.rules.type
并不只是为了取代 Loader 那么简单,更重要的目的是在 JavaScript Module 之外增加对其它资源 —— Asset Module 的原生支持,让 Webpack 有机会介入这些多媒体资源的解析、生成过程,从而有机会实现更标准、高效的资源处理模型。