webpack原理之loader的分类

一、loader分类

1. 同步loader

同步loader是最常用的loader,当webpack需要处理一个文件时,同步loader会对其进行同步处理,并且返回一个处理后的模块(一个JavaScript模块或是其他类型的模块)。这些处理器必须是同步的,也就是它们不能异步处理代码块。

例如:我们可以使用json-loader将JSON文件转换为JavaScript对象:

module.exports = function(source) {
  return `module.exports = ${JSON.stringify(JSON.parse(source))};`;
};

在Webpack配置中,使用该Loader如下:

module: {
  rules: [
    {
      test: /\.json$/,
      use: 'json-loader'
    }
  ]
}

通过使用同步Loader,我们可以在不影响打包效率的前提下,对源代码进行更精细的处理,从而满足各种需求。同时,同步Loader也比异步Loader更加易于编写和测试。

2. 异步loader

异步loader是一种特殊的loader,它们可以工作在一个异步方式而不是同步方式。这些loader可以在webpack打包处理文件的时候异步读取和处理资源文件,并且在完成后返回一个JavaScript模块。通过使用异步loader,我们可以在处理大型和复杂的资源文件时提高webpack打包处理的效率。

异步Loader可以使Webpack处理大型文件时提升解析速度,同时也能处理一些比较耗时的任务。可以使用import()和require.ensure()函数来定义需要异步处理的模块,然后使用webpack特定的注释语法来指定需要使用哪个Loader进行处理,例如://!async-loader。

异步Loader有两种类型:callback类型和promise类型。callback类型的异步Loader使用this.callback()方法来返回处理结果,而promise类型的异步Loader则使用return Promise.resolve()方法来返回处理结果。

callback类型以babel-loader为例,其异步loader代码如下所示:

module.exports = function(source) {
  const callback = this.async(); // 获取callback函数
  babel.transform(
    source,
    {},
    (err, result) => {
      if (err) {
        callback(err);
      } else {
        callback(null, result.code); // 返回处理结果
      }
    }
  );
};

异步loader需要使用this.async()获取callback函数,然后在处理完代码后调用callback将结果返回给webpack。

当同时使用异步Loader和同步Loader时,Webpack会先执行同步Loader,然后再执行异步Loader。这意味着,同步Loader可以对模块进行预处理,然后将它传递给异步Loader进行进一步处理。

例如,以下是一个同时使用异步Loader和同步Loader的示例:

module.exports = {
  module: {
    rules: [
      {
        test: /\.js$/,
        use: [
          {
            loader: 'async-loader'
          },
          {
            loader: 'sync-loader'
          }
        ]
      }
    ]
  }
};

该配置中,Webpack先执行sync-loader,然后执行async-loader,这意味着,sync-loader可以对模块进行预处理,然后将它传递给async-loader进行进一步处理。

总的来说,异步Loader可以使Webpack处理模块的速度更快,同时也能处理一些比较耗时的任务。在使用异步Loader时,需要注意异步Loader和同步Loader的执行顺序,以确保Loader能够正确处理模块。

3. Raw Loader

Raw loader是一个原始的loader,它将文件的原始形式(即二进制格式)作为字符串输出。这种loader被广泛用于处理代码和样式中的静态资源(如图片,字体和其他文件类型)。当我们使用raw loader时,我们可以将这些静态文件嵌入到CSS文件或者JavaScript文件中,以便将它们传递给webpack处理器。

(1) 安装raw-loader

npm install raw-loader --save-dev

(2) 在webpack配置文件中引入raw-loader

module.exports = {
  module: {
    rules: [
      {
        test: /\.txt$/,
        use: 'raw-loader'
      }
    ]
  }
};

(3) 在JavaScript文件中使用raw-loader导入文件内容

var txt = require("./file.txt");

console.log(txt);

(4). raw loader的写法

raw loader的实现非常简单,只需要读取文件内容,并返回一个字符串即可。

module.exports = function(source) {
  return JSON.stringify(source);
}

在这个例子中,source变量代表从文件中读取到的内容。JSON.stringify()方法将source转换成字符串,并将它作为模块的输出。

(5). 注意事项

raw loader只能导入文本文件,不能导入二进制文件。如果你想加载其他类型的文件,你需要使用合适的loader。

此外,在使用raw loader时,要注意文件的大小,如果文件过大,可能会导致性能问题。对于大文件,可以使用Source Map来定位错误和问题。

4. Pitching Loader

pitching loader是一种特殊类型的loader,它在webpack打包处理时运行在正常的loader之前。这些loader会在处理请求之前被调用,并且它们可以拦截请求,改变它们希望处理的文件,或者直接返回一个JavaScript模块。这种loader通常用于处理和传递loader的选项或其他变量。

module.exports = function () {};
module.exports.pitch = function (remainingRequest, precedingRequest, data) {
  // 对之前loader的结果进行处理
  let result = preprocess(remainingRequest);
  // 返回处理后的结果,传给下一个loader
  return `module.exports = ${JSON.stringify(result)};`
};

使用方式:

module: {
  rules: [
    {
      test: /\.js$/,
      use: [
        'my-pitching-loader',
        'my-sync-loader'
      ]
    }
  ]
}

以上就是webpack中的四种常见的loader,不同的loader适用于处理不同类型的资源文件,我们应根据需要选择最适合的loader。当我们需要加载资源文件时,我们可以在webpack配置文件中指定所需要的loader、选择合适的loader进行处理。

二、loader API

附赠一波loader的常用api

Loader API对应方法描述
this.queryN/A获取传递给 loader 的 query 对象
this.emitWarning()this.emitWarning()发出一个警告信息,告诉 Webpack 发出一个 "warning" 通知
this.emitError()this.emitError()发出一个错误信息,告诉 Webpack 发出一个 "error" 通知
this.callback()this.callback(err, content)结束 loader 执行,如果 content 不为 null,传递给下一个 loader
this.async()this.async()告诉 Webpack 在 loader 完成时继续处理,如果 loader 涉及到异步处理
this.addDependency()this.addDependency(file)告诉 Webpack 当前 loader 依赖文件,当文件改变时,Webpack 会重新编译
this.addContextDeependency()this.addContextDependency(dir)告诉 Webpack 当前 loader 依赖目录,当目录改变时,Webpack 会重新编译
this.resourcePathN/A获取当前正在处理的文件路径
this.resourceQueryN/A获取当前正在处理的文件的查询参数
this.contextN/A获取当前正在处理的文件所在目录的绝对路径
this.sourceMapN/A如果 webpack 配置中开启了 source map,获取当前正在处理的代码的 sourcemap 信息
this.targetN/A获取编译的目标平台,值为 webnode
this.loadModulethis.loadModule(request: string, callback: function(err, source, sourceMap, module))加载另一个模块
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

jieyucx

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值