一、loader的分类
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提供了添加前缀的方式来避免这种问题
- 使用 ! 前缀,将禁用所有已配置的 normal loader(普通 loader)
import Styles from '!style-loader!css-loader?modules!./styles.css';
- 使用 !! 前缀,将禁用所有已配置的 loader(preLoader, loader, postLoader)
import Styles from '!!style-loader!css-loader?modules!./styles.css';
- 使用 -! 前缀,将禁用所有已配置的 preLoader 和 loader,但是不禁用 postLoaders
import Styles from '-!style-loader!css-loader?modules!./styles.css';
三、手写loader
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传递给loadername: "kobe",age: 24,},},],},
loader的详解就到这里了,可以看着官方文档和百度试着自己写一个loader,下一篇再说plugin的详解了