loader,webpack的核心之一,因为webpack只能识别js,json文件,那么jsx,ts,vue,less,sass这类文件的就需要使用loader处理。
Loader 本质上是导出为函数的 JavaScript 模块。它接收资源文件或者上一个 Loader 产生的结果作为入参,也可以用多个 Loader 函数组成 loader chain(链),最终输出转换后的结果。它接收三个参数:content 源文件的内容,map SourceMap 数据,meta 数据,可以是任何内容。
loader的执行顺序:从右往左执行。
举个栗子,如果我们去配置一个简单的脚手架,那么怎么去处理对应less,sass,styles这类文件呢,
loader链
module: {
rules: [
{
test: /\.less$/,
use: [
"style-loader", //将css内容变成style标签插入到html中去
"css-loader", //解析css文件的路径等
"less-loader", //将less=>css
],
},
],
},
其实在生产环境中会替换掉style-loader替换为 MiniCssExtractPlugin.loader将CSS代码从打包后的JavaScript文件中提取出来,单独生成一个CSS文件。以免造成闪屏现象。
按照loader的执行顺序分类:前置 , 普通 , 行内 ,后置( loader的类型和他本身没有任何关系,而是和配置的enforce属性有关系)
举个栗子,处理图片,图标这些资源
module: {
rules: [
{
test: /\.(png|jpe?g|gif|svg)$/,
type: "asset",
enforce: "pre", //这里也可以是post,默认不写就是normal
},//图片的处理
],
},
loader的执行会有两个阶段,pithching阶段与normal阶段
pitching阶段:调用loader上的 pitch 方法,按照 后置(post)、行内(inline)、普通(normal)、前置(pre) 的顺序调用。
normal阶段: Loader 上的 常规方法,按照 前置(pre)、普通(normal)、行内(inline)、后置(post) 的顺序调用。我们需要对文件进行转换,就是在这个阶段去操作的。
首先在loaders下定义三个loader
function oneMalLoader(content, map, meta) {
console.log(" one 的normal阶段");
return content
}
oneMalLoader.pitch = function (remainingRequest, previousRequest, data) {
console.log(" one 的pitch阶段");
}
module.exports = oneMalLoader;
function towMalLoader(content, map, meta) {
console.log(" tow 的normal阶段");
return content
}
towMalLoader.pitch = function (remainingRequest, previousRequest, data) {
console.log(" tow 的pitch阶段");
}
module.exports = towMalLoader;
function threeMalLoader(content, map, meta) {
console.log(" three 的normal阶段");
return content
}
threeMalLoader.pitch = function (remainingRequest, previousRequest, data) {
console.log(" three 的pitch阶段");
}
module.exports = threeMalLoader;
这里的话直接使用的最常用的方式去调用的
resolveLoader: {
//找loader的时候,先去loaders目录下找,找不到再去node_modules下面找
modules: ["loaders", "node_modules"],
},
module: {
rules: [
{
test: /\.js$/,
use: [
"one-loader","tow-loader","three-loader"
],
}
],
},
然后run一run,看看打印的结果

所以说在 Loader 的运行过程中,如果发现该 Loader 上有pitch属性,会先执行 pitch 阶段,再执行 normal 阶段。
pitch阶段的参数有三个PreviousRequest、CurrentRequest、remainingRequest
function oneMalLoader(content, map, meta) {
console.log(" one 的normal阶段参数",'content',content,'map',map,'meta',meta);
console.log('this.data',this.data,'one0loader normal阶段的参数');
return content
}
oneMalLoader.pitch = function (remainingRequest, previousRequest, data) {
console.log(" one 的pitch阶段");
console.log('remainingRequest',remainingRequest, 'previousRequest',previousRequest, 'data',data,'one0loader pitch阶段的参数');
this.data.name='李华'
}
module.exports = oneMalLoader;
先打印一下看一下

这就很好理解了
PreviousRequest代表的是之前执行过pitch阶段的loader,
remainingRequest代表未执行过pitch阶段的loader,
data,可以用于数据传递。即在 pitch 函数中往 data 对象上添加数据,之后在 normal 函数中通过 this.data 的方式读取已添加的数据,也就是注入上下文。
那么写一下简单的loader吧
例如,清除我们项目中的console.log
module.exports = function cleanLogLoader(content, map, meta) {
/**
* 将源文件正则替换后返回
*/
return content.replace(/console\.log\(.*\);?/g, "");
};
先看一下最开始打包后的代码

使用clearnLog loader打包后的代码

个人的理解还不是很深入,后续学习深入学习后会继续补充。
共有 0 条评论