プラグインは webpack エコシステムの重要な要素であり、コミュニティが webpack のコンパイルプロセスを活用するための強力な方法を提供します。プラグインは、コンパイル全体で発生する主要なイベントにフックできます。どの段階でも、プラグインはcompiler
と、該当する場合は現在のcompilation
に完全にアクセスできます。
webpack のプラグインインターフェイスのバックボーンを提供するtapable
ユーティリティから始めましょう。
この小さなライブラリは webpack のコアユーティリティですが、同様のプラグインインターフェイスを提供するために他の場所でも使用できます。webpack の多くのオブジェクトはTapable
クラスを拡張しています。このクラスは、プラグインがコンパイル中に実行されるカスタムビルドステップを注入するために使用できるtap
、tapAsync
、およびtapPromise
メソッドを公開します。
詳細については、ドキュメントを参照してください。3つのtap
メソッドと、それらを提供するフックの理解が不可欠です。Tapable
を拡張するオブジェクト(例:コンパイラ)、それらが提供するフック、および各フックの型(例:SyncHook
)が記載されます。
使用されるフックと適用されるtap
メソッドに応じて、プラグインはさまざまな方法で機能します。この仕組みは、Tapable
によって提供されるフックと密接に関連しています。コンパイラフックはそれぞれ、利用可能なtap
メソッドを示す基になるTapable
フックを記述しています。
したがって、どのイベントにtap
するかによって、プラグインの動作が異なる場合があります。たとえば、compile
ステージにフックする場合は、同期のtap
メソッドのみを使用できます
compiler.hooks.compile.tap('MyPlugin', (params) => {
console.log('Synchronously tapping the compile hook.');
});
ただし、AsyncHook
を利用するrun
の場合、tapAsync
またはtapPromise
(および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.');
}
);
結論として、compiler
にhook
するためのさまざまな方法があり、それぞれがプラグインが適切と判断したとおりに実行できます。
他のプラグインがtap
できるコンパイルにカスタムフックを提供するには、次のことを行う必要があります。
コンパイルフック用のモジュールスコープのWeakMap
を作成します
const compilationHooks = new WeakMap<Compilation, MyHooks>();
interface MyHooks {
custom: SyncHook<[number, string]>;
}
プラグインに静的メソッドを作成します
static getCompilationHooks(compilation: Compilation) : MyHooks {
let hooks = compilationHooks.get(compilation);
if(hooks === undefined) {
compilationHooks.set(compilation, hooks = {
custom: new SyncHook()
});
}
return hooks;
}
プラグインで以下のようにフックを呼び出します
const hooks = MyPlugin.getCompilationHooks(compilation);
hooks.custom.call(1, 'hello');
他のプラグインもカスタムフックにアクセスできます
import MyPlugin from 'my-plugin';
const hooks = MyPlugin.getCompilationHooks(compilation);
hooks.custom.tap('OtherPlugin', (n, s) => {
// magic
});
繰り返しになりますが、さまざまなフッククラスとその仕組みの詳細については、tapable
のドキュメントを参照してください。
プラグインは、デフォルトで進捗メッセージを stderr に出力するProgressPlugin
を介して進捗状況を報告できます。進捗状況の報告を有効にするには、webpack CLIの実行時に--progress
引数を渡します。
ProgressPlugin
のreportProgress
関数に異なる引数を渡すことで、出力される内容をカスタマイズできます。
進捗状況を報告するには、プラグインは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
を参照してください。
ロギングAPIは webpack 4.37のリリース以降利用可能です。stats 設定
でlogging
が有効になっている場合や、インフラストラクチャロギング
が有効になっている場合、プラグインはメッセージをログに記録できます。これは、それぞれのロガー形式(統計、インフラストラクチャ)で出力されます。
compilation.getLogger('PluginName')
を使用することを推奨します。この種のロギングは統計に保存され、それに応じてフォーマットされます。ユーザーはこれをフィルタリングしてエクスポートできます。compiler.getInfrastructureLogger('PluginName')
を使用できます。infrastructure
ロギングの使用は統計に保存されないため、フォーマットされません。通常、コンソール/ダッシュボード/GUIに直接ログが記録されます。ユーザーはこれをフィルタリングできます。compilation.getLogger ? compilation.getLogger('PluginName') : console
を使用して、compilation
オブジェクトでgetLogger
メソッドをサポートしない古い webpack バージョンが使用されている場合のフォールバックを提供できます。利用可能なすべてのcompiler
フックと、それらが利用可能にするパラメーターの詳細なリストについては、コンパイラフックセクションを参照してください。