最初に、Hot Module Replacement(HMR)はまだ実験的な機能であることに注意したい。
HMRは、実行中のアプリケーションでモジュールを交換する(およびモジュールを追加/削除する)方法です。基本的に、ページ全体をリロードすることなく、変更されたモジュールを更新できます。
ドキュメンテーション
前提条件:
HMRではそれほどではありませんが、リンクは次のとおりです。
これらの回答をドキュメントに追加します。
どのように機能しますか?
アプリビューから
アプリのコードは、HMRランタイムに更新の確認を要求します。HMRランタイムは更新をダウンロード(非同期)し、更新が利用可能であることをアプリのコードに通知します。アプリのコードは、HMRランタイムに更新の適用を要求します。HMRランタイムは更新を適用します(同期)。アプリのコードでは、このプロセスでユーザーの操作が必要な場合と必要でない場合があります(ユーザーが決定)。
コンパイラー(webpack)ビューから
通常のアセットに加えて、コンパイラーは「更新」を発行して、以前のバージョンからこのバージョンに更新できるようにする必要があります。「更新」には2つの部分が含まれます。
- 更新マニフェスト(json)
- 1つまたは複数の更新チャンク(js)
マニフェストには、新しいコンパイルハッシュとすべての更新チャンクのリストが含まれています(2)。
更新チャンクには、このチャンク内のすべての更新されたモジュールのコード(またはモジュールが削除された場合はフラグ)が含まれています。
さらに、コンパイラーはモジュールとチャンクIDがこれらのビルド間で一貫していることを確認します。「レコード」jsonファイルを使用して、ビルド間でそれらを保存します(またはメモリに保存します)。
モジュールビューから
HMRはオプトイン機能であるため、HMRコードを含むモジュールにのみ影響します。ドキュメントでは、モジュールで使用できるAPIについて説明しています。一般に、モジュール開発者は、このモジュールの依存関係が更新されたときに呼び出されるハンドラーを記述します。また、このモジュールが更新されたときに呼び出されるハンドラーを作成することもできます。
ほとんどの場合、すべてのモジュールでHMRコードを記述する必要はありません。モジュールにHMRハンドラーがない場合、更新はバブルアップします。つまり、単一のハンドラーで完全なモジュールツリーの更新を処理できます。このツリーの1つのモジュールが更新されると、モジュールツリー全体が再ロードされます(再ロードのみで、転送はされません)。
HMRランタイムビューから(技術)
モジュールシステムランタイムがモジュールparents
とを追跡するための追加コードが発行されますchildren
。
管理側では、ランタイムはcheck
およびの2つのメソッドをサポートしますapply
。
A check
は、更新マニフェストに対してHTTP要求を行います。このリクエストが失敗した場合、利用可能なアップデートはありません。そうでない場合、更新されたチャンクのリストは、現在ロードされているチャンクのリストと比較されます。ロードされたチャンクごとに、対応する更新チャンクがダウンロードされます。モジュールの更新はすべて、更新としてランタイムに保存されます。ランタイムがready
状態に切り替わります。つまり、更新がダウンロードされ、適用する準備ができています。
準備完了状態の新しいチャンク要求ごとに、更新チャンクもダウンロードされます。
このapply
メソッドは、更新されたすべてのモジュールに無効のフラグを付けます。無効なモジュールごとに、モジュール内の更新ハンドラーまたはすべての親の更新ハンドラーが必要です。それ以外の場合は無効なバブルが発生し、すべての親も無効としてマークします。このプロセスは、「バブルアップ」が発生しなくなるまで続きます。エントリポイントまでバブルすると、プロセスは失敗します。
これで、すべての無効なモジュールが破棄され(破棄ハンドラー)、アンロードされます。次に、現在のハッシュが更新され、すべての「受け入れ」ハンドラーが呼び出されます。ランタイムがidle
状態に戻り、すべてが通常どおり続行されます。
どうすればよいですか?
LiveReloadの代替として開発で使用できます。実際、webpack-dev-serverは、ページ全体を再ロードする前にHMRで更新しようとするホットモードをサポートしています。webpack/hot/dev-server
エントリポイントを追加して、でdev-serverを呼び出すだけです--hot
。
また、更新メカニズムとして本番環境で使用することもできます。ここでは、HMRをアプリと統合する独自の管理コードを記述する必要があります。
一部のローダーは、ホットアップデート可能なモジュールをすでに生成しています。たとえばstyle-loader
、スタイルシートを交換できます。特別なことをする必要はありません。
CSS(1つのスタイルシート)とJSモジュールをディスクに保存するときに、ページをリロードしたり、LiveReloadなどのプラグインを使用したりせずに更新したいとします。これはHot Module Replacementが役立ちますか?
はい
どのような作業を行う必要がありますか。HMRはすでに何を提供していますか?
ここに小さな例があります:https : //webpack.js.org/guides/hot-module-replacement/
モジュールは、「承認」した場合にのみ更新できます。したがってmodule.hot.accept
、親または親の親のモジュールが必要になります。たとえば、ルーターは適切な場所、またはサブビューです。
webpack-dev-serverでのみ使用する場合は、webpack/hot/dev-server
エントリポイントとして追加します。それ以外の場合はcheck
、およびを呼び出すHMR管理コードが必要ですapply
。
意見:何がそんなにクールなのですか?
- LiveReloadですが、すべてのモジュールの種類に対応しています。
- 生産で使用できます。
- 更新はコード分割を尊重し、アプリの使用済み部分の更新のみをダウンロードします。
- アプリケーションの一部に使用でき、他のモジュールには影響しません
- HMRが無効になっている場合、すべてのHMRコードがコンパイラーによって削除されます(それをでラップします
if(module.hot)
)。
注意事項
- これは実験的なものであり、あまりテストされていません。
- いくつかのバグが予想されます。
- 理論的には本番環境で使用できますが、深刻なものに使用するには時期尚早かもしれません。
- モジュールIDはコンパイル間で追跡する必要があるため、それらを保存する必要があります(
records
)。
- オプティマイザーは、最初のコンパイル後にモジュールIDを最適化できなくなります。バンドルサイズへの影響。
- HMRランタイムコードはバンドルサイズを増やします。
- 本番環境で使用する場合、HMRハンドラーをテストするために追加のテストが必要です。これはかなり難しいかもしれません。