CC 4.0 授權

本節內容源自以下連結的內容,並受 CC BY 4.0 授權的約束。

如果未特別聲明,以下內容可以假設為基於原始內容進行修改和刪除的結果。

範例

以下章節提供一些不同類型 loader 的基本範例。請注意,mapmeta 參數是選用的,請參閱下方的 this.callback

同步 Loader

可以使用 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 在內部會將 loader 轉換為非同步,無論它是同步 loader,都是基於技術和效能考量。

非同步 Loader

對於非同步 loader,使用 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);
  });
};

'Raw' Loader

預設情況下,資源檔案會轉換為 UTF-8 字串並傳遞給 loader。loader 可以透過將 raw 設定為 true 來接收原始的 Buffer。每個 loader 可以將其處理結果作為 StringBuffer 傳遞,Rspack 編譯器會在 loader 之間進行轉換。

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

Pitching loader

Loader 永遠 從右到左調用。在某些情況下,loader 只關心請求背後的metadata,並且可以忽略先前 loader 的結果。Loader 上的 pitch 方法會在 loader 實際執行之前(從右到左),從左到右調用。

對於以下 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 正常執行

通常,如果 loader 非常簡單,只匯出正常的階段 Hook

module.exports = function (source) {};

那麼,將會跳過 pitching 階段。

那麼,為什麼 loader 會利用 "pitching" 階段?

首先,傳遞到 pitch 方法的資料也會在執行階段作為 this.data 公開,並且對於擷取和共享週期早期資訊可能很有用。

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

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

其次,如果 loader 在 pitch 方法中提供結果,則該程序會轉過來並跳過其餘的 loader。在上面的範例中,如果 b-loader 的 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 了解詳細資訊。