Plugin API

外掛程式是 webpack 生態系統中的關鍵部分,並提供社群一個強大的方式來利用 webpack 的編譯程序。外掛程式能夠掛勾在每次編譯中觸發的主要事件。在每個步驟中,外掛程式都可以完全存取編譯器,並在適用的情況下存取目前的編譯

讓我們從介紹tapable工具程式開始,它提供了 webpack 外掛程式介面的核心。

Tapable

這個小型函式庫是 webpack 中的核心實用程式,但也可以在其他地方使用,以提供類似的外掛介面。webpack 中的許多物件都延伸了 Tapable 類別。這個類別公開了 taptapAsynctapPromise 方法,外掛可以使用這些方法來注入自訂的建置步驟,這些步驟會在編譯過程中觸發。

請參閱 文件 以了解更多資訊。了解三個 tap 方法以及提供它們的掛鉤至關重要。會記錄延伸 Tapable 的物件(例如編譯器)、它們提供的掛鉤以及每個掛鉤的類型(例如 SyncHook)。

外掛類型

根據使用的掛鉤和套用的 tap 方法,外掛可以以不同的方式運作。這種運作方式與 Tapable 提供的 掛鉤 密切相關。編譯器掛鉤 各自記錄底層 Tapable 掛鉤,指出哪些 tap 方法可用。

因此,根據您 tap 進入哪個事件,外掛的執行方式可能不同。例如,在掛入 compile 階段時,只能使用同步 tap 方法

compiler.hooks.compile.tap('MyPlugin', (params) => {
  console.log('Synchronously tapping the compile hook.');
});

但是,對於使用 AsyncHookrun,我們可以使用 tapAsynctapPromise(以及 tap

compiler.hooks.run.tapAsync(
  'MyPlugin',
  (source, target, routesList, callback) => {
    console.log('Asynchronously tapping the run hook.');
    callback();
  }
);

compiler.hooks.run.tapPromise('MyPlugin', (source, target, routesList) => {
  return new Promise((resolve) => setTimeout(resolve, 1000)).then(() => {
    console.log('Asynchronously tapping the run hook with a delay.');
  });
});

compiler.hooks.run.tapPromise(
  'MyPlugin',
  async (source, target, routesList) => {
    await new Promise((resolve) => setTimeout(resolve, 1000));
    console.log('Asynchronously tapping the run hook with a delay.');
  }
);

這個故事的寓意是,有各種方式可以 hook 進入 compiler,每個方式都允許您的外掛根據需要執行。

自訂掛鉤

若要提供自訂掛勾供其他外掛程式進行 tap 編譯,您需要執行下列動作

  1. 為編譯掛勾建立模組範圍的 WeakMap

    const compilationHooks = new WeakMap<Compilation, MyHooks>();
    
    interface MyHooks {
      custom: SyncHook<[number, string]>;
    }
  2. 在您的外掛程式上建立靜態方法

    static getCompilationHooks(compilation: Compilation) : MyHooks {
      let hooks = compilationHooks.get(compilation);
      if(hooks === undefined) {
        compilationHooks.set(compilation, hooks = {
          custom: new SyncHook()
        });
      }
      return hooks;
    }
  3. 在您的外掛程式中呼叫如下掛勾

    const hooks = MyPlugin.getCompilationHooks(compilation);
    
    hooks.custom.call(1, 'hello');
  4. 其他外掛程式也可以存取您的自訂掛勾

    import MyPlugin from 'my-plugin';
    
    const hooks = MyPlugin.getCompilationHooks(compilation);
    
    hooks.custom.tap('OtherPlugin', (n, s) => {
      // magic
    });

再次查看 文件,以進一步了解不同的掛勾類別及其運作方式。

回報進度

外掛程式可透過 ProgressPlugin 回報進度,預設會將進度訊息列印至 stderr。若要啟用進度回報,請在執行 webpack CLI 時傳遞 --progress 參數。

可以透過傳遞不同的參數至 ProgressPluginreportProgress 函數,自訂列印輸出。

若要回報進度,外掛程式必須使用 context: true 選項tap 進入掛勾

compiler.hooks.emit.tapAsync(
  {
    name: 'MyPlugin',
    context: true,
  },
  (context, compiler, callback) => {
    const reportProgress = context && context.reportProgress;
    if (reportProgress) reportProgress(0.95, 'Starting work');
    setTimeout(() => {
      if (reportProgress) reportProgress(0.95, 'Done work');
      callback();
    }, 1000);
  }
);

reportProgress 函數可以使用這些參數呼叫

reportProgress(percentage, ...args);
  • percentage:此參數未使用;相反地,ProgressPlugin 會根據目前的掛勾計算百分比。
  • ...args:任意數量的字串,將傳遞至 ProgressPlugin 處理常式,以回報給使用者。

請注意,只有編譯器和編譯掛勾的子集支援 reportProgress 函數。請參閱 ProgressPlugin 以取得完整清單。

記錄

自 webpack 4.37 發布以來,日誌記錄 API 已可用。當在 統計資料設定 中啟用 logging 和/或啟用 基礎架構日誌記錄 時,外掛程式可能會記錄訊息,這些訊息將以各自的記錄器格式(統計資料、基礎架構)列印出來。

  • 外掛程式應優先使用 compilation.getLogger('PluginName') 進行日誌記錄。這種日誌記錄會儲存在統計資料中並進行相應的格式化。使用者可以過濾和匯出它。
  • 外掛程式可以使用 compiler.getInfrastructureLogger('PluginName') 進行日誌記錄。使用 基礎架構 日誌記錄不會儲存在統計資料中,因此不會進行格式化。它通常會直接記錄到控制台/儀表板/GUI。使用者可以過濾它。
  • 外掛程式可以使用特定的後備邏輯來偵測日誌記錄支援 compilation.getLogger ? compilation.getLogger('PluginName') : console,以便在使用不支援 compilation 物件上的 getLogger 方法的舊版 webpack 時提供後備。

後續步驟

請參閱 編譯器掛鉤 部分,以取得所有可用的 compiler 掛鉤和它們提供的參數的詳細清單。

7 貢獻者

thelarkinnpksjcee-cloudbyzykEugeneHlushkowizardofhogwartssnitin315