プラグインは 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フックと、それらが利用可能にするパラメーターの詳細なリストについては、コンパイラフックセクションを参照してください。