カスタムWebpackプラグインの作成
webpackを使用したことがある場合は、おそらくwebpackプラグインについて聞いたことがあるでしょう。 プラグインは、webpackの実装とアーキテクチャを拡張するための優れたオプションです。 webpackのソースコードを見ると、約80% ofのコードがプラグインを使用して実装されています。 これは、webpackのコア部分を分離するのに役立ち、コードのメンテナンスが向上します。
webpackは次の概念もサポートしています loaders
これはwebpackの拡張にも役立ち、 resolvers
. これらは主にソースコードを変換するために使用されます。 カバーするのは別のトピックであり、カスタムローダーを作成する方法についての記事もすぐに書くでしょう。
カスタムWebpackプラグインの作成について詳しく説明する前に、モジュールバンドラーの基本的な動作と、Webpackが内部でどのように機能するかを知る必要があります。 基本的なモジュールバンドラーの目標は、ソースコードを読み取り、依存関係を見つけることです。これは、依存関係の解決と呼ばれます。
依存関係の解決中に、バンドラーはモジュールマッピング(モジュールマップ)を実行し、それらを1つのファイルにバンドルし、1つのモジュールにパッケージ化します。 webpackはこれらの部分を高度な方法で実行し、効率的にするために他のいくつかの手順も追加します。 次の手順を使用して、webpackのアーキテクチャを破ることができます。
- コンパイラ:トップレベルのAPIがあり、webpackの実行を制御するためのフックを提供します。
- コンパイルまたは依存関係グラフ:コンパイラーによって返され、依存関係グラフの作成を開始します。
- Resolver :提供されたエントリパスの絶対パスを作成し、結果、リクエスト、パス、コンテキストなどの詳細を返します。
- Parser :AST(抽象構文木)を作成し、requiresやimportsなどの興味深いものを探して、依存関係オブジェクトを作成します。
- モジュールファクトリ:これらのオブジェクトはmoduleFactory関数に渡され、モジュールを作成します。
- Templates :モジュールオブジェクトのデータバインディングを実行し、バンドルされたファイルにコードを作成します。
webpackは、コンパイラ、パーサー、およびコンパイル用のフックを提供します。 tapable と呼ばれるライブラリを使用します。これは、webpackチームによって維持され、メソッドを利用できる強力で強力なフックの作成に役立ちます。
フックとタッピングインメソッドとは何ですか?
フックはイベントに似ており、フックを利用することは、イベントをリッスンして適切なメソッドを実行するリスナーのようなものです。 たとえば、次のようなDOM関連のイベントリスナーを配置する場合:
window.addEventListener('load', (event) => {
loadEventListerner(event)
});
これで、 load
イベントまたはフックであり、 loadEventListener
を利用しています。
webpackはどのようにテープを使用し、プラグインはどのように画像に組み込まれますか?
実際の例を見て、webpackがどのようにテーピングを使用するかを説明しましょう。 ピザ配達アプリからピザを注文しているとしましょう。 これで、メニューの確認、注文のカスタマイズ、そして最終的に料金を支払って注文するなど、プロセスに関連する一連のステップがあります。 ここから先、ピザが届くまで、アプリは注文の進行状況に関する通知を送信します。
この例では、ピザ配達アプリを webpack に、自分自身を webpackプラグインに、通知をtapableによって作成されたフックに置き換えることができます。
webpackは、コンパイラ、コンパイル、パーサーステージのフックをtaableを使用して作成し、プラグインはそれらをタップまたはリッスンしてそれに応じて動作します。
これらの理論と概念を十分に理解して、コードを見せてください。
この投稿では、作成されたバンドルファイルのサイズをチェックし、サイズ制限に基づいてエラーまたは警告をログに記録する単純なwebpackプラグインを作成します。 これらのサイズ制限はプラグインオプションでも渡すことができ、デフォルトのサイズ制限は3KBのままにします。 したがって、出力ファイルプラグインがサイズ制限を超えている場合は常にエラーメッセージをログに記録し、それを下回っている場合は安全なメッセージをログに記録し、サイズ制限と等しい場合はユーザーに警告します。
プラグインのコードはここにあります。
最初にプロジェクトをセットアップしましょう。
プロジェクトディレクトリで、npmまたはYarnを使用してwebpackをインストールします。
$ npm init -y
$ npm install webpack webpack-cli --save-dev
この後、作成します src
ディレクトリと index.js
その中のファイル。入力パスまたはエントリパスがポイントし、作成します。 webpack.config.js
プロジェクトのルートディレクトリにあるファイル。
これで、プラグインのディレクトリを作成して、次のような名前を付けることができます。 bundlesize-webpack-plugin
を作成します index.js
そのディレクトリ内。
プロジェクト構造は次のようになります。
webpack-Plugin-demo-directory
|- webpack.config.js
|- package.json
|- /src
|- index.js
|- /bundlesize-webpack-plugin
|- index.js
次のビルドスクリプトをに追加します scripts
package.jsonファイル内:
"build": "webpack"
そしてあなたの中で bundlesize-webpack-plugin/index.js
次のコードを記述します。
module.exports = class BundlesizeWebpackPlugin {
constructor(options) {
this.options = options;
}
apply(compiler) {
console.log("FROM BUNDLESIZE PLUGIN");
}
};
これについてはすぐに説明します。
今あなたの webpack.config.js
、次のコードを記述します。
const { resolve } = require("path");
const bundlesizeplugin = require("./bundlesize-webpack-plugin");
module.exports = {
entry: resolve(__dirname, "src/index.js"),
output: {
path: resolve(__dirname, "bin"),
filename: "bundle.js"
},
plugins: [new bundlesizeplugin()]
};
今すぐ実行 npm run build
.
ターミナルに「FROMBUNDLESIZEPLUGIN」というメッセージが表示されます。
これで、webpackプラグインが作成されました。
それを分解する
すべてのwebpackプラグインには apply
webpackとwebpackによって呼び出されるメソッドは、そのメソッドの引数としてコンパイラインスタンスを提供します。
プラグインは、クラスベースにすることも、関数ベースにすることもできます。 プラグインが関数ベースの場合、関数の引数もコンパイラです。 この記事ではクラスベースを使用することをお勧めします。
Webpackのソースコードとがどのように実装されているかをここで確認できます
クラスのコンストラクターには、 options
口論。 これは、プラグインがいくつかのオプションを受け入れる場合に使用されます。 合格します sizeLimit
オプションとして、渡されない場合、デフォルトは3KBになります。
これで、コンストラクターメソッドを次のように変更できます。
constructor(options) {
this.options = options || {
sizeLimit: 3
};
}
あなたは合格することができます sizeLimit
プラグインとして options
同様に、このように:
plugins: [
new bundlesizeplugin({
sizeLimit: 4
})
]
の webpack.config.js
、エントリポイントについて言及し、webpackにバンドルファイルをという名前のフォルダに出力するように指示しているだけです。 bin
で bundle.js
ファイル、およびwebpackにプラグインを使用するように指示します bundlesize-webpack-plugin
フォルダ。
プロジェクトの準備ができたので、アセットサイズを確認して、 sizeLimit
. を使用します compiler.hooks.done
コンパイル作業が完了し、バンドルファイルが生成されるときに発行されるフック。 バンドルされたファイルの詳細は、この方法で取得できます。
非同期のフックがいくつかあり、それらに非同期のタッピング方法を使用できることに注意してください。 ここでこれらについて学ぶことができます
apply(compiler) {
compiler.hooks.done.tap("BundleSizePlugin", (stats) => {
const {
path,
filename
} = stats.compilation.options.output;
})
}
ここでは、コンパイラの doneフックまたはイベントにtappingを実行しています。メソッドの最初の引数は、webpackが参照に使用するプラグイン名であり、2番目のメソッドはかかるコールバック stats
引数として。 あなたはを使用して統計の内容を確認することができます console.log(stats)
、コンパイルとそのフックで使用可能なファイルに関するすべての可能な詳細を含む大きなオブジェクトが表示されます。 出力プロパティからパスとファイル名を抽出しています。 これからは、Node.jsのコアライブラリを使用してファイルの詳細を取得するだけです。 path
と fs
モジュール:
apply(compiler) {
compiler.hooks.done.tap("BundleSizePlugin", stats => {
const { path, filename } = stats.compilation.options.output;
const bundlePath = resolve(path, filename);
const { size } = fs.statSync(bundlePath);
console.log(size); // size in bytes
});
}
簡単でしょ?
これで、 this StackOverflow answer のような関数を使用して、サイズをバイトからkbに変換できます。
今それを単に比較してください sizeLimit
と console.log
適切なメッセージ:
apply(compiler) {
compiler.hooks.done.tap("BundleSizePlugin", stats => {
const { path, filename } = stats.compilation.options.output;
const bundlePath = resolve(path, filename);
const { size } = fs.statSync(bundlePath);
const { bundleSize, fullSizeInfo } = formatBytes(size);
const { sizeLimit } = this.options;
if (bundleSize < sizeLimit) {
console.log(
"Safe:Bundle-Size",
fullSizeInfo,
"\n SIZE LIMIT:",
sizeLimit
);
} else {
if (bundleSize === sizeLimit) {
console.warn(
"Warn:Bundle-Size",
fullSizeInfo,
"\n SIZE LIMIT:",
sizeLimit
);
} else {
console.error(
"Unsafe:Bundle-Size",
fullSizeInfo,
"\n SIZE LIMIT:",
sizeLimit
);
}
}
});
}
それでおしまい! これで、バンドルサイズをチェックし、サイズ制限に基づいてレポートする独自のWebpackプラグインができました。
これをnpmレジストリで公開できるようになりました。
webpackがプラグインに効果的であると考える標準はほとんどありません。 webpack-defaultを出発点として使用できます。
私がすでに公開しているbundlesize-webpack-pluginも独自のフックを拡張しており、それらはテーピングを使用して作成されていることに注意してください。 実装はmasterブランチにあります。
概要
- Webpackが内部でどのように機能し、そのアーキテクチャがどのように実装されているかを確認しました
- フックとそれを利用することの意味について学びました
- プラグインがシステムにどのように組み込まれるかを見ました
- バンドルされたファイルのサイズをチェックするための簡単なプラグインを作成しました