1.pre:前置loader
2.normal:普通loader
3.inline:内联loader
4.post:后置loader
pre > normal > inline > post,相同类型的loader执行顺序为:从右到左,从下到上
module:{
rules:[{
enforce:"pre", //通过这个参数来定义loader的类型,默认是normal类型
test:/\.js/,
loader:"loader"
}]
}
内联loader不能用上面的方式定义,必须用下面的方式
// 多个loader用!分开,要给loader传参就必须用?后面接参数,就比如?module,module就是css-loader的参数
import style from "style-loader!css-loader?module!./style.css"
使用内联loader会遇到一个问题,就比如上面的代码使用了css-loader,可能在配置文件里面也配置了css-loader,这样就会造成重复,所以内联loader提供了添加前缀的方式来避免这种问题
import Styles from '!style-loader!css-loader?modules!./styles.css';
import Styles from '!!style-loader!css-loader?modules!./styles.css';
import Styles from '-!style-loader!css-loader?modules!./styles.css';
1.定义同步testLoader.js文件
/**
* content:文件内容
* map SourceMap
* meta 别人loader传递的参数,必须是处理同一个文件的loader
*/
module.exports = function (content, map, meta) {
/**
* callback参数
* 第一个参数是报错信息,没有报错就是null,其余参数就是上面loader接收的参数
* 这种写法也叫同步loader,同步loader里面不能写异步操作
*/
this.callback(null, content, map, { whh: 1 });
};
2.定义异步testLoader.js文件
/**
* content:文件内容
* map SourceMap
* meta 别人loader传递的参数,必须是处理同一个文件的loader
*/
module.exports = function (content, map, meta) {
const callback = this.async(); //等同于await,有异步操作的时候,这样才能拿到值
setTimeout(() => {
callback(null, content, map, { whh: 1 });
}, 1000);
};
3.定义raw loader
/**
* content:文件内容
* map SourceMap
* meta 别人loader传递的参数,必须是处理同一个文件的loader
*/
module.exports = function(content,map,meta){
//这里的content就变成二进制buffer数据了,可以用于处理图片等等媒体文件
console.log(content);
return content; //不需要做太多操作的时候,就可以直接返回content,不需要使用callback
}
module.exports.raw = true; //开启
4.定义picth loader
/**
* content:文件内容
* map SourceMap
* meta 别人loader传递的参数,必须是处理同一个文件的loader
* 这个函数就是普通函数
*/
module.exports = function (content, map, meta) {
return content;
};
/**
* {
test: /\.js$/,
use: ["loader1","loader2","loader3","loader4","loader5"],
},
假如有多个loader来处理js文件,每个loader都有定义pitch函数,那么他们的顺序是先从左到右执行loader里面的picth函数,
然后再从右到左执行普通函数,pitch函数的return不是必需的,如果在执行picth函数途中,某个loader的pitch函数有return,
那么整个picth执行会结束,然后从当前loader开始从右到左执行普通的函数
举例说明,
执行顺序为loader1里面的pitch,然后loader2里面的pitch,一直到loader5里面的pitch,然后再执行loader5里面的普通函数,
一直到loader1里面的普通函数,整个流程就是loader的执行过程,但是如果执行到loader3里面的pitch,发现有return,
那么就不会执行loader4和loader5里面的pitch函数和普通函数,会直接执行loader3的普通函数,然后loader2的普通函数,
最后到loader1的普通函数,然后执行结束
*/
module.exports.pitch = function () {
console.log("picth");
return "result";
};
使用方法:
{
test: /\.lth$/,
loader: path.resolve(__dirname, "../loader/testLoader.js"),
},
还有很多很多API,就不详细说了,看官方文档或者其他人的博客吧
官方链接
这里主要说一下传参的api,这个还是很重要的
module.exports = function (content, map, meta) {
const obj = this.getOptions(); //通过这个来获取传递进来的参数
console.log(obj); //{ name: 'kobe', age: 24 }
return content;
};
{
test: /\.lth$/,
use: [
{
loader: path.resolve(__dirname, "../loader/testLoader.js"),
options: { //通过options传递给loader
name: "kobe",
age: 24,
},
},
],
},
loader的详解就到这里了,可以看着官方文档和百度试着自己写一个loader,下一篇再说plugin的详解了