編譯鉤子

資訊

Rspack 的主要編譯邏輯在 Rust 端運行。 由於穩定性、效能和架構等因素,當使用鉤子將 Rust 端編譯物件傳輸到 JavaScript 端後,對這些物件的修改將不會同步到 Rust 端。 因此,大多數鉤子都是「唯讀」的。

概述

buildModule

唯讀

在模組建置開始之前觸發。

  • 類型: SyncHook<[Module]>
  • 參數
    • Module:模組實例

executeModule

唯讀

如果存在編譯時執行模組,則在執行時會呼叫此鉤子。

  • 類型: SyncHook<[ExecuteModuleArgument, ExecuteModuleContext]>
  • 參數
    • ExecuteModuleArgument:編譯時執行模組的參數
    • ExecuteModuleContext:編譯時執行模組的內容

succeedModule

唯讀

當模組建置成功時執行。

  • 類型: SyncHook<[Module]>
  • 參數
    • Module:模組實例

finishModules

唯讀

當所有模組都已建置且沒有錯誤時呼叫。

  • 類型: AsyncSeriesHook<[Module[]]>
  • 參數
    • Module[]:模組實例清單

seal

當編譯停止接受新模組並開始最佳化模組時呼叫。

  • 類型: SyncHook<[]>

optimizeModules

唯讀

在模組最佳化階段開始時呼叫。

  • 類型: SyncBailHook<[Module[]]>
  • 參數
    • Module[]:模組實例清單

afterOptimizeModules

唯讀

在模組最佳化完成後呼叫。

  • 類型: SyncBailHook<[Module[]]>
  • 參數
    • Module[]:模組實例清單

optimizeTree

唯讀

在最佳化依賴樹之前呼叫。

  • 類型: AsyncSeriesHook<[Chunk[], Module[]]>
  • 參數
    • Chunk[]:區塊實例清單
    • Module[]:模組實例清單

optimizeChunkModules

唯讀

在樹狀最佳化之後呼叫,在區塊模組最佳化開始時呼叫。

  • 類型: AsyncSeriesBailHook<[Chunk[], Module[]]>
  • 參數
    • Chunk[]:區塊實例清單
    • Module[]:模組實例清單

additionalTreeRuntimeRequirements

在樹狀執行階段需求收集之後呼叫。

  • 類型: SyncHook<[Chunk, Set<RuntimeGlobals>]>
  • 參數
    • Chunk:區塊實例
    • Set<RuntimeGlobals>:執行階段需求

可以透過修改執行階段需求集合在此處新增其他內建執行階段模組。

rspack.config.js
module.exports = {
  entry: './index.js',
  plugins: [
    {
      apply(compiler) {
        const { RuntimeGlobals } = compiler.webpack;
        compiler.hooks.thisCompilation.tap('CustomPlugin', compilation => {
          compilation.hooks.additionalTreeRuntimeRequirements.tap(
            'CustomPlugin',
            (_, set) => {
              // add a runtime module which define `__webpack_require__.h`
              set.add(RuntimeGlobals.getFullHash);
            },
          );
        });
      },
    },
  ],
};
index.js
// will print hash of this compilation
console.log(__webpack_require__.h);

runtimeRequirementInTree

在將執行階段模組新增至編譯期間呼叫。

  • 類型: HookMap<SyncBailHook<[Chunk, Set<RuntimeGlobals>]>>
  • 參數
    • Chunk:區塊實例
    • Set<RuntimeGlobals>:執行階段需求

可以透過修改執行階段需求集合或呼叫 compilation.addRuntimeModule 來新增自訂執行階段模組,從而在此處新增其他內建執行階段模組。

rspack.config.js
module.exports = {
  entry: './index.js',
  plugins: [
    {
      apply(compiler) {
        const { RuntimeGlobals, RuntimeModule } = compiler.webpack;
        class CustomRuntimeModule extends RuntimeModule {
          constructor() {
            super('custom');
          }

          generate() {
            const compilation = this.compilation;
            return `
            __webpack_require__.mock = function(file) {
              return ${RuntimeGlobals.publicPath} + "/subpath/" + file;
            };
          `;
          }
        }

        compiler.hooks.thisCompilation.tap('CustomPlugin', compilation => {
          compilation.hooks.runtimeRequirementInTree
            .for(RuntimeGlobals.ensureChunkHandlers)
            .tap('CustomPlugin', (chunk, set) => {
              // add a runtime module to access public path
              set.add(RuntimeGlobals.publicPath);
              compilation.addRuntimeModule(chunk, new CustomRuntimeModule());
            });
        });
      },
    },
  ],
};
index.js
// will print "/subpath/index.js"
console.log(__webpack_require__.mock('index.js'));

runtimeModule

在將執行階段模組新增至編譯後呼叫。

  • 類型: SyncHook<[RuntimeModule, Chunk]>
  • 參數
    • RuntimeModule:執行階段模組實例
    • Chunk:區塊實例

可以透過其 source 屬性修改此執行階段模組產生的程式碼。

rspack.config.js
module.exports = {
  plugins: [
    {
      apply(compiler) {
        const { RuntimeGlobals } = compiler.webpack;
        compiler.hooks.compilation.tap('CustomPlugin', compilation => {
          compilation.hooks.runtimeModule.tap(
            'CustomPlugin',
            (module, chunk) => {
              if (module.name === 'public_path' && chunk.name === 'main') {
                const originSource = module.source.source.toString('utf-8');
                module.source.source = Buffer.from(
                  `${RuntimeGlobals.publicPath} = "/override/public/path";\n`,
                  'utf-8',
                );
              }
            },
          );
        });
      },
    },
  ],
};
index.js
// will print "/override/public/path"
console.log(__webpack_require__.p);

processAssets

在發射之前處理資產。

  • 類型: AsyncSeriesHook<Assets>
  • 鉤子參數
    • name: string — 插件的名稱
    • stage: Stage — 要加入的階段(請參閱下方的 資產處理階段
  • 參數
    • Assets: Record<string, Source>:純物件,其中鍵是資產的路徑名稱,而值是由 Source 表示的資產資料。

資產處理範例

  • PROCESS_ASSETS_STAGE_ADDITIONAL 階段發射新的資產
compiler.hooks.thisCompilation.tap('MyPlugin', compilation => {
  compilation.hooks.processAssets.tap(
    {
      name: 'MyPlugin',
      stage: compilation.PROCESS_ASSETS_STAGE_ADDITIONAL,
    },
    assets => {
      const { RawSource } = compiler.webpack.sources;
      const source = new RawSource('This is a new asset!');
      compilation.emitAsset('new-asset.txt', source);
    },
  );
});
  • 更新現有的資產
compiler.hooks.thisCompilation.tap('MyPlugin', compilation => {
  compilation.hooks.processAssets.tap(
    {
      name: 'MyPlugin',
      stage: compilation.PROCESS_ASSETS_STAGE_ADDITIONS,
    },
    assets => {
      const asset = assets['foo.js'];
      if (!asset) {
        return;
      }

      const { RawSource } = compiler.webpack.sources;
      const oldContent = asset.source();
      const newContent = oldContent + '\nconsole.log("hello world!")';
      const source = new RawSource(newContent);

      compilation.updateAsset(assetName, source);
    },
  );
});
  • 移除資產
compiler.hooks.thisCompilation.tap('MyPlugin', compilation => {
  compilation.hooks.processAssets.tap(
    {
      name: 'MyPlugin',
      stage: compilation.PROCESS_ASSETS_STAGE_OPTIMIZE,
    },
    assets => {
      const assetName = 'unwanted-script.js';
      if (assets[assetName]) {
        compilation.deleteAsset(assetName);
      }
    },
  );
});

資產處理階段

以下是支援階段的清單。 Rspack 會從上到下依序執行這些階段。 請根據您需要執行的操作選取適當的階段。

  • PROCESS_ASSETS_STAGE_ADDITIONAL — 將額外資產新增至編譯。
  • PROCESS_ASSETS_STAGE_PRE_PROCESS — 資產的基本前處理。
  • PROCESS_ASSETS_STAGE_DERIVED — 從現有資產衍生新的資產。
  • PROCESS_ASSETS_STAGE_ADDITIONS — 將額外區段新增至現有資產,例如橫幅或初始化程式碼。
  • PROCESS_ASSETS_STAGE_OPTIMIZE — 以一般方式最佳化現有資產。
  • PROCESS_ASSETS_STAGE_OPTIMIZE_COUNT — 最佳化現有資產的計數,例如透過合併它們。
  • PROCESS_ASSETS_STAGE_OPTIMIZE_COMPATIBILITY — 最佳化現有資產的相容性,例如新增 polyfill 或供應商前綴。
  • PROCESS_ASSETS_STAGE_OPTIMIZE_SIZE — 優化現有資源的大小,例如透過最小化或省略空白字元。
  • PROCESS_ASSETS_STAGE_DEV_TOOLING — 將開發工具新增至資源,例如透過提取原始碼對應 (source map)。
  • PROCESS_ASSETS_STAGE_OPTIMIZE_INLINE — 透過將資源內嵌到其他資源中來優化現有資源的數量。
  • PROCESS_ASSETS_STAGE_SUMMARIZE — 總結現有資源的列表。
  • PROCESS_ASSETS_STAGE_OPTIMIZE_HASH — 優化資源的雜湊值,例如透過產生資源內容的真實雜湊值。
  • PROCESS_ASSETS_STAGE_OPTIMIZE_TRANSFER — 優化現有資源的傳輸,例如透過準備一個壓縮 (gzip) 檔案作為獨立資源。
  • PROCESS_ASSETS_STAGE_ANALYSE — 分析現有資源。
  • PROCESS_ASSETS_STAGE_REPORT — 建立用於報告目的的資源。

afterProcessAssets

唯讀

processAssets hook 完成且沒有錯誤後呼叫。

  • 類型: SyncHook<Assets>
  • 參數
    • Assets: Record<string, Source>:資源實例列表

afterSeal

唯讀

在 seal 階段之後呼叫。

  • 類型: AsyncSeriesHook<[]>

chunkHash

唯讀

觸發以發出每個 chunk 的雜湊值。

  • 類型: SyncHook<[Chunk, Hash]>
  • 參數
    • Chunk:區塊實例
    • Hash:chunk 雜湊實例

chunkAsset

唯讀

當來自 chunk 的資源被新增到編譯時觸發。

  • 類型: SyncHook<[Chunk, string]>
  • 參數
    • Chunk:區塊實例
    • string:資源檔案名稱

childCompiler

唯讀

在設定子編譯器後執行。

  • 類型: SyncHook<[Compiler, string, number]>
  • 參數
    • Compiler:子編譯器實例
    • string:子編譯器名稱
    • number:子編譯器索引

statsPreset

唯讀

這個 hook 就像當使用 preset 時會觸發的一系列動作。它會接收一個 options 物件。當一個外掛程式管理 preset 時,它應該仔細地變更這個物件中的設定,而不要取代現有的設定。

  • 類型: SyncHook<[Partial<StatsOptions>, CreateStatsOptionsContext]>
  • 參數
    • Partial<StatsOptions>:統計資料選項
    • CreateStatsOptionsContext:統計資料內容

這是一個說明用的外掛程式範例

compilation.hooks.statsPreset.for('my-preset').tap('MyPlugin', options => {
  if (options.all === undefined) options.all = true;
});

這個外掛程式確保對於 preset "my-preset",如果 all 選項未定義,則預設為 true

statsNormalize

唯讀

這個 hook 用於將 options 物件轉換為一致的格式,以便後續 hook 輕鬆使用。它還確保遺失的選項會設定為其預設值。

  • 類型: SyncHook<[Partial<StatsOptions>, CreateStatsOptionsContext]>
  • 參數
    • Partial<StatsOptions>:統計資料選項
    • CreateStatsOptionsContext:統計資料內容

這是一個說明用的外掛程式範例

compilation.hooks.statsNormalize.tap('MyPlugin', options => {
  if (options.myOption === undefined) options.myOption = [];

  if (!Array.isArray(options.myOption)) options.myOptions = [options.myOptions];
});

在這個外掛程式中,如果遺失了 myOption,則會將其設定為 []。此外,它還確保 myOption 始終是一個陣列,即使它最初定義為單一值。

statsFactory

唯讀

這個 hook 提供對特定選項的 StatsFactory 類別的存取權。

  • 類型: SyncHook<[StatsFactory, StatsOptions]>
  • 參數

statsPrinter

唯讀

這個 hook 提供對特定選項的 StatsPrinter 類別的存取權。

  • 類型: SyncHook<[StatsPrinter, StatsOptions]>
  • 參數