CC 4.0 许可证

本节内容来自以下链接的内容,并受 CC BY 4.0 许可证约束。

除非另有说明,以下内容可被认为是基于原始内容修改和删除的结果。

示例

以下部分提供了一些不同类型加载器的基本示例。请注意,mapmeta 参数是可选的,请参见下面的 this.callback

同步加载器

可以使用 returnthis.callback 同步返回转换后的 content

sync-loader.js
module.exports = function (content, map, meta) {
  return someSyncOperation(content);
};

this.callback 方法更加灵活,因为它允许传递多个参数,而不仅仅是 content

sync-loader-with-multiple-results.js
module.exports = function (content, map, meta) {
  this.callback(null, someSyncOperation(content), map, meta);
  return; // always return undefined when calling callback()
};
信息

出于技术和性能方面的考虑,Rspack 内部会将加载器转换为异步加载器,无论其是否为同步加载器。

异步加载器

对于异步加载器,使用 this.async 来获取 callback 函数

async-loader.js
module.exports = function (content, map, meta) {
  var callback = this.async();
  someAsyncOperation(content, function (err, result) {
    if (err) return callback(err);
    callback(null, result, map, meta);
  });
};
async-loader-with-multiple-results.js
module.exports = function (content, map, meta) {
  var callback = this.async();
  someAsyncOperation(content, function (err, result, sourceMaps, meta) {
    if (err) return callback(err);
    callback(null, result, sourceMaps, meta);
  });
};

'原始' 加载器

默认情况下,资源文件会被转换为 UTF-8 字符串并传递给加载器。加载器可以通过将 raw 设置为 true 来接收原始 Buffer。每个加载器都可以将处理结果作为 StringBuffer 传递,Rspack 编译器会将其转换为加载器所需的格式。

raw-loader.js
module.exports = function (content) {
  assert(content instanceof Buffer);
  // ...
};
module.exports.raw = true;

投放加载器

加载器始终从右到左调用。在某些情况下,加载器只关心请求背后的元数据,而可以忽略先前加载器的结果。加载器上的 pitch 方法是从左到右调用,在加载器真正执行(从右到左)之前调用。

对于以下 use 配置

rspack.config.js
module.exports = {
  //...
  module: {
    rules: [
      {
        //...
        use: ['a-loader', 'b-loader', 'c-loader'],
      },
    ],
  },
};

将执行以下步骤

|- a-loader `pitch` |- b-loader `pitch` |- c-loader `pitch` |- 请求的模块被选为依赖 |- c-loader 正常执行 |- b-loader 正常执行 |- a-loader 正常执行

通常,如果加载器足够简单,只导出普通阶段的钩子

module.exports = function (source) {};

那么投放阶段将被跳过。

那么为什么加载器要利用“投放”阶段呢?

首先,传递给 pitch 方法的数据也会在执行阶段作为 this.data 公开,这对于从循环早期捕获和共享信息很有用。

module.exports = function (content) {
  return someSyncOperation(content, this.data.value);
};

module.exports.pitch = function (remainingRequest, precedingRequest, data) {
  data.value = 42;
};

其次,如果加载器在 pitch 方法中提供结果,则流程会反转,跳过剩余的加载器。在上面的示例中,如果 b-加载器的 pitch 方法返回了一些内容

module.exports = function (content) {
  return someSyncOperation(content);
};

module.exports.pitch = function (remainingRequest, precedingRequest, data) {
  if (someCondition()) {
    return (
      'module.exports = require(' +
      JSON.stringify('-!' + remainingRequest) +
      ');'
    );
  }
};

上面的步骤将缩短为

|- a-loader `pitch` |- b-loader `pitch` 返回模块 |- a-loader 正常执行

对于实际应用的示例,style-loader 利用第二个优势来分发请求。请访问 style-loader 了解详细信息。