loader的本质就是一个个的函数,在模块的编译阶段,会使用这些loader对源代码进行处理,处理时,一般都会生成AST解析树,这样可以方便处理。
单个loader的使用没有什么好记录的。
多个loader的使用是用一个use数组,loader的使用顺序是从下往上,也就是从use数组的后往前执行的,下面的load1、loader2、loader3是我自己定义的loader
use: [
'loader1',
'loader2',
{
loader: 'loader3',
options: {
name: 'jack',
age: 18
}
}
]
为了方便webpack找到loader,我们可以配置loader的解析规则,也就是解析路径
// 配置loader的解析规则
resolveLoader: {
// 指定找loader去哪个地方找
modules: [
// 这是默认值
'node_modules',
// 指定自己的
path.resolve(__dirname, 'loaders')
]
},
下面是loader1.js的内容,注释已经写得很清楚了,值得注意的是,module.exports和module.exports.pitch这两个函数的执行顺序是不一样的,pitch是按照use数组从前往后执行,所以比较适合用来对loader做一些预处理。
// loader本质上是一个函数
// content就是源文件或者后一个loader传过来的内容
// module.exports = function (content, map, meta) {
// // console.log(content);
// console.log(111);
// return content;
// }
// 下面这种写法和上面那种写法是一样的(同步loader)
module.exports = function (content, map, meta) {
console.log(111);
// 第一个参数是是否有错误,第三四个参数是可选的
this.callback(null, content, map, meta);
}
// pitch方法会根据loader的顺序从前往后执行
module.exports.pitch = function () {
console.log('pitch 111');
}
下面是loader2中的内容,不同于loader1的是,它是一个异步的loader,异步loader的好处就是它可以执行一些异步操作,可以等异步操作完之后再执行接下来的loader,性能更好。
// 异步loader
module.exports = function (content, map, meta) {
console.log(222);
// 调用this.async() 告诉webpack这是一个异步loader,需要等待 callback() 回调之后再进行下一个loader处理
const callback = this.async();
setTimeout(() => {
callback(null, content)
}, 1000)
console.log('loader2中的异步')
}
module.exports.pitch = function () {
console.log('pitch 222');
}
下面是loader3中的内容,主要就是获取loader的选项和验证loader的选项
//getOptions方法可以来获取loader的选项(这个包webpack没有自带)
const { getOptions } = require('loader-utils');
// 验证options是不是符合规范(这个包是webpack内部自带的包)
const { validate } = require('schema-utils');
const schema = require('./schema');
module.exports = function (content, map, meta) {
// 获取options
const options = getOptions(this);
console.log(333, options);
// 校验options是否合法,如果不合法,会报错
validate(schema, options, {
name: 'loader3'
})
return content;
}
module.exports.pitch = function () {
console.log('pitch 333');
}
这是schema.json中的内容
{
"type": "object",
"properties": {
"name": {
"type": "string",
"description": "名称~"
}
},
"additionalProperties": true
}
下面是执行打包后的结果,可以看到loader中的内容按预期执行