关于webpack loader的那些事儿

2023-03-23 10:49:19 浏览数 (1)

写在前面

最近遇到了一个很特殊的需求,业务代码打包后需要运行在两个不同的环境中,而两个环境中的属性有非常多的差异,我想在打包阶段来处理这些差异,所以就需要自定义一个loader来处理设计到的相关文件,在此之前,得先学习一下loader相关的知识点。

loader是什么

loader本质上是一个导出为函数的JavaScript模块,loader runner库会调用这个函数,然后将上一个loader产生的结果或者资源文件传入进去,并返回处理后的资源给下一个资源。

接收参数

Loader函数会接收三个参数

  • content:需要处理的资源文件内容
  • map:sourcemap相关的数据
  • meta:一些元数据
代码语言:javascript复制
module.exports = function(content,map,meta){
        //函数处理代码....
    return content
}
返回值

loader有两种方式来返回处理后的数据

  • 直接将处理之后的数据通过return返回
  • 通过this.callback来返回处理之后的数据
this.callback

this.callback接收两个参数

  • 第一个参数必须是 Error 或者 null,来代表loader的处理是否出错
  • 第二个参数是一个 string或者Buffer

所以,通常在有错误的情况下,我们会使用 this.callback

代码语言:javascript复制
module.exports.pitch = function(content,map,meta){   
    //函数处理代码....    
    this.callback(null,content)   
    //return content 
}
this.async

如果loader里面的处理是异步的,我们需要调用 this.async 方法来获取 callback 函数

代码语言:javascript复制
module.exports = function(content) { 
    var callback = this.async(); 
    setTimeout(function() { 
        callback(null, content   "-async-simple"); 
    }, 50); 
};

配置自定义loader

假如我们写了一个关于txt文本文件的loader,需要在webpack中使用的话,我们需要在loader字段中进行配置

代码语言:javascript复制
//...
rules:[
    //...
        {
          test: /.txt?$/,
          use:[{
            // loader文件的相对路径
            loader:'./txt_loader.js',
          }]
        }
]

或者通过resolveLoader字段,配置resolveLoader属性,可以告诉webpack可以直接去哪个文件夹内寻找loader文件。

代码语言:javascript复制
module.exports = {
    module: {
        rules: [
            {
                test: /.js$/,
                //直接写loader函数的文件名称
                use: ['myLoader']
            }
        ]
    }
    resolveLoader: {
        //此处配置从哪里找loader
        modules: ['./loaders','node_modules']
    }
}
获取配置传参

很多情况下,我们是需要传递一些参数,在打包的流程中对loader进行配置

代码语言:javascript复制
//...
rules:[
    //...
        {
          test: /.txt?$/,
          use:[{
            loader:'./txt_loader.js',
            // 加入loader配置
            options:{
                isChinese:false
                //.....
            }
          }]
        }
]

然后我们可以在loader中通过getOptions方法来进行获取

代码语言:javascript复制
const { getOptions } = require('loader-utils') 
modules.exports = function(content){  
    //...
    const options = getOptions(this)    //处理函数...    
    return content 
}

loader的分类

NormalLoader

定义

代码语言:javascript复制
module.exports = function(content,map,meta){   
    //函数处理代码....    
    return content 
}
PitchLoader

定义

代码语言:javascript复制
module.exports.pitch = function(content,map,meta){   
    //函数处理代码....    
    return content 
}
联系

pitch loader的整体执行顺序都在normal loader之前,并且可以通过meta来将数据传递到对应的normal loader上

webpack对loader的分类

在 Webpack 中,loader 可以被分为 4 类:

  • pre 前置:可以通过enforce设置
  • post 后置:可以通过enforce设置
  • normal 普通:默认所有的loader都是normal
  • inline 行:在行内设置的loader是inline(如:import 'loader1!loader2!./test.js'

其中 pre 和 post loader,可以通过 rule 对象的 enforce 属性来指定

执行顺序
  • PitchingLoader的执行顺序:post, inline, normal, pre;
  • NormalLoader的执行顺序:pre, normal, inline, post;

最后

感谢你能看到这里,本文总结了loader的一些基础知识,希望对你有用,下一篇文章,笔者将详细介绍解决业务需求的loader,如果可以的话,不妨留个赞再走呢。

0 人点赞