我们常用 raw-loader、url-loader、file-loader 来处理图片、字体等资源文件,Webpack5 为我们提供了一种更简单、更方便的方式来替换上述 loader,这既是本文我们将要介绍的 Asset Module(即资源模块)。
Webpack5 为我们提供了 asset/resource
、asset/inline
、asset/source
、asset
四种资源类型,具体介绍如下所示:
asset/resource
:将资源文件输出到指定的输出目录,作用等同于 file—loader
;asset/inline
:将资源文件内容以指定的格式进行编码(一般为 base64
),然后以 data URI 的形式嵌入到生成的 bundle
中,作用等同于 url-loader
;asset/source
:将资源文件的内容以字符串的形式嵌入到生成的 bundle
中,作用相当于 raw-loader
;asset
:作用等同于设置了 limit
属性的 url-loader
,即资源文件的大小如果小于 limit
的值(默认值为 8kb
),则采用 asset/inline
模式,否则采用 asset/resource
模式。Asset Module 的使用非常简单,只需将之前的配置:
// webpack.config.js
module.exports = {module: {rules: [{test: /\.(png|jpe?g|gif)$/i,use: [{loader: 'file-loader',},],},],},
};
调整为以下配置即可:
// webpack.config.js
module.exports = {module: {rules: [{test: /\.(png|jpe?g|gif)$/i,type: 'asset' // 可用值:asset/resource、asset/inline、asset/source、asset},],},
};
除了通过配置文件,我们也可通过内联语法来使用相关 loader,比如:
// src/index.js
import avatar from 'file-loader!./avatar.png';
上例中,Webpack 将调用 file-loader
来处理资源 ./avatar.png
,那么在 Webpoack5 的 Asset Module 中又该如何进行内联操作呢?先看下面的例子:
// src/index.js
import avatar from './avatar.png?image';
// webpack.config.js
module.exports = {module: {rules: [{type: 'asset/resource',resourceQuery: /image/,},],},
};
通过例子可知,Webpack5 的 Asset Module 内联语法涉及以下两个步骤:
query
参数(比如上例中的 ?image
);resourceQuery
配置项。其中 resourceQuery
的常用格式为:
字符串
:上例的配置为 ?image
;* 正则表达式
:上例的配置为 /image/
;* 对象
:* { and: [] }
:必须匹配数组中的所有条件;* { or: [] }
:只需匹配数组中的任一条件;* { not: [] }
:必须排除数组中的所有条件。默认情况下,在处理 resource
类型的资源时,相关资源会被输出到 output.path 目录下(文件命名规则为 [hash][ext][query]
),我们可通过设置 output.assetModuleFilename
来改变其输出目录:
// webpack.config.js
module.exports = {output: {path: path.resolve(__dirname, 'dist'),assetModuleFilename: './static/images/[hash][ext][query]',},
};
这里需要注意的是,assetModuleFilename
的值须为相对路径
,如值为绝对路径
,将抛出以下异常:
Invalid configuration object. Webpack has been initialized using a configuration object that does not match the API schema.
- configuration.output.assetModuleFilename: A relative path is expected. However, the provided value "/home/nanjingboy/test-webpack/static/images/[hash][ext][query]" is an absolute path!
该配置仅适用于 asset
和 asset/resource
资源类型。
在配置 module.rules
时,可配置 generator
来对资源的处理进行进一步控制,该配置有以下几个属性:
filename
:* 作用等同于上文所说的 output.assetModuleFilename
,值也必须为相对路径
;* 如果同时指定了该属性和 output.assetModuleFilename
,将忽略 output.assetModuleFilename
的值;dataUrl
:* 在处理 inline
类型的资源时,该资源默认对资源进行 base64
编码,可通过该属性来改变其编码方式;* 该属性值为函数,其签名为 (content: string) => string
;* 该属性仅适用于 asset
和 asset/inline
资源类型。dataUrlCondition.maxSize
:* 当 type
为 asset
时,如果资源大小小于 8kb
,按照 asset/inline
的规则处理资源,否则按照 asset/resource
的规则处理资源;* 可通过指定该属性来改变其界限值(单位为 byte
);* 该属性仅适用于 asset
资源类型。上述配置的示例如下:
// webpack.config.js
module.exports = {modules: {rules: [{test: /\.(png|jpe?g|gif)$/i,type: 'asset',generator: {filename: './static/images/[hash][ext][query]',dataUrl: content => {return encode(content.toString());},dataUrlCondition: {maxSize: 4 * 1024 // 4kb,单位为 byte,默认值为 8kb},},},],},
};
本文我们对 Webpack5 Asset Module(即资源模块)的使用进行了简短介绍,如有疏漏之处还望诸位海涵,祝大家快乐编码每一天。