# 七.配置 loader
# 1.loader 匹配规则
module.exports = {
// ...
module: {
rules: [
//`test` 和 `include` 都用于匹配 `resource` 路径,是 `resource.test` 和 `resource.include` 的简写
{
test: /\.jsx?/, // 条件
include: [path.resolve(__dirname, "src")], // 条件
use: "babel-loader", // 规则应用结果
}, // 一个 object 即一条规则
// ...
],
},
}
2
3
4
5
6
7
8
9
10
11
12
13
14
换一种写法
module.exports = {
// ...
rules: [
{
resource: {
// resource 的匹配条件
test: /\.jsx?/,
include: [path.resolve(__dirname, "src")], //匹配条件通常都使用请求资源文件的绝对路径来进行匹配
},
// 比较少用到的 `issuer`,则是声明依赖请求的源文件的绝对路径,如果要使用 issuer 匹配,便是 issuer: { test: ... }
use: "babel-loader",
},
// ...
],
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 2.规则条件配置
大多数情况下,配置 loader 的匹配条件时,只要使用 test
字段就好了,很多时候都只需要匹配文件后缀名来决定使用什么 loader,webpack 的规则提供了多种配置形式:
{ test: ... }
匹配特定条件{ include: ... }
匹配特定路径{ exclude: ... }
排除特定路径{ and: [...] }
必须匹配数组中所有条件{ or: [...] }
匹配数组中任意一个条件{ not: [...] }
排除匹配数组中所有条件
上述的所谓条件的值可以是:
- 字符串:必须以提供的字符串开始,所以是字符串的话,这里我们需要提供绝对路径
- 正则表达式:调用正则的
test
方法来判断匹配 - 函数:(path) => boolean,返回
true
表示匹配 - 数组:至少包含一个条件的数组
- 对象:匹配所有属性值的条件
通过例子来帮助理解:
rules: [
{
test: /\.jsx?/, // 正则
include: [
path.resolve(__dirname, 'src'), // 字符串,注意是绝对路径
], // 数组
// ...
},
{
test: {
js: /\.js/,
jsx: /\.jsx/,
}, // 对象,不建议使用
not: [
(value) => { /* ... */ return true; }, // 函数,通常需要高度自定义时才会使用
],
},
],
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 3.module type
javascript/auto
:即 webpack 3 默认的类型,支持现有的各种 JS 代码模块类型 —— CommonJS、AMD、ESMjavascript/esm
:ECMAScript modules,其他模块系统,例如 CommonJS 或者 AMD 等不支持,是.mjs
文件的默认类型javascript/dynamic
:CommonJS 和 AMD,排除 ESMjavascript/json
:JSON 格式数据,require
或者import
都可以引入,是.json
文件的默认类型webassembly/experimental
:WebAssembly modules,当前还处于试验阶段,是.wasm
文件的默认类型
如果不希望使用默认的类型的话,在确定好匹配规则条件时,我们可以使用 type
字段来指定模块类型,例如把所有的 JS 代码文件都设置为强制使用 ESM 类型:
{
test: /\.js/,
include: [
path.resolve(__dirname, 'src'),
],
type: 'javascript/esm', // 这里指定模块类型
},
2
3
4
5
6
7
上述做法是可以帮助你规范整个项目的模块系统,但是如果遗留太多不同类型的模块代码时,建议还是直接使用默认的 javascript/auto
。
webpack 后续的开发计划会增加对更多模块类型的支持,例如极其常见的 CSS 和 HTML 模块类型,这个特性值得我们期待一下。
# 4.使用 loader 配置
当然,在当前版本的 webpack 中,module.rules
的匹配规则最重要的还是用于配置 loader,我们可以使用 use
字段:
rules: [
{
test: /\.less/,
use: [
'style-loader', // 直接使用字符串表示 loader
{
loader: 'css-loader',
options: {
importLoaders: 1
},
}, // 用对象表示 loader,可以传递 loader 配置等
{
loader: 'less-loader',
options: {
noIeCompat: true
}, // 传递 loader 配置
},
],
},
],
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
我们看下上述的例子,先忽略 loader 的使用情况,单纯看看如何配置。use
字段可以是一个数组,也可以是一个字符串或者表示 loader 的对象。如果只需要一个 loader,也可以这样:use: { loader: 'babel-loader', options: { ... } }
。
我们还可以使用 options
给对应的 loader 传递一些配置项,这里不再展开。当你使用一些 loader 时,loader 的说明一般都有相关配置的描述。
# 5.loader 应用顺序
一个 style.less 文件会途径 less-loader、css-loader、style-loader 处理,成为一个可以打包的模块。
loader 的应用顺序在配置多个 loader 一起工作时很重要,通常会使用在 CSS 配置上,除了 style-loader 和 css-loader,你可能还要配置 less-loader 然后再加个 postcss 的 autoprefixer 等。
rules: [ //这样无法法保证 eslint-loader 在 babel-loader 应用前执行
{
test: /\.js$/,
exclude: /node_modules/,
loader: "eslint-loader",
},
{
test: /\.js$/,
exclude: /node_modules/,
loader: "babel-loader",
},
],
2
3
4
5
6
7
8
9
10
11
12
webpack 在 rules
中提供了一个 enforce
的字段来配置当前 rule 的 loader 类型,没配置的话是普通类型,我们可以配置 pre
或 post
,分别对应前置类型或后置类型的 loader。
还有一种行内 loader,即我们在应用代码中引用依赖时直接声明使用的 loader,如 const json = require('json-loader!./file.json')
这种。不建议在应用开发中使用这种 loader,后续我们还会再提到。
loader 按照前置 -> 行内 -> 普通 -> 后置的顺序执行:
rules: [
{
enforce: 'pre', // 指定为前置类型
test: /\.js$/,
exclude: /node_modules/,
loader: "eslint-loader",
},
]
2
3
4
5
6
7
8
# 6.使用 noParse
除了 module.rules
字段用于配置 loader 之外,还有一个 module.noParse
字段,可以用于配置哪些模块文件的内容不需要进行解析。对于一些不需要解析依赖(即无依赖) 的第三方大型类库等,可以通过这个字段来配置,以提高整体的构建速度。
使用
noParse
进行忽略的模块文件中不能使用import
、require
、define
等导入机制。
module.exports = {
// ...
module: {
noParse: /jquery|lodash/, // 正则表达式
// 或者使用 function
noParse(content) {
return /jquery|lodash/.test(content)
},
},
}
2
3
4
5
6
7
8
9
10
11
noParse
从某种程度上说是个优化配置项,日常也可以不去使用。