1. ホーム
  2. ジャバスクリプト

[解決済み】WebpackのHot Module Replacementとは一体何ですか?

2022-04-17 19:01:47

質問

を読みました。 少ない ページ Webpackのホットモジュール置き換えについて。

また サンプルアプリ その 使用する .

これだけ読んでもまだピンとこない。

どうすればいいのでしょうか?

  1. 開発時のみ使用し、本番では使用しないことを想定しているのでしょうか?
  2. LiveReloadと同じで、自分で管理する必要があるのでしょうか?
  3. WebpackDevServerはLiveReloadと何らかの形で統合されているのでしょうか?

CSS(1つのスタイルシート)とJSモジュールをディスクに保存するときに、ページを再読み込みすることなく、またLiveReloadなどのプラグインを使用せずに、更新したいとします。これはHot Module Replacementが助けてくれるものでしょうか?どのような作業が必要で、HMRがすでに提供しているものは何ですか?

どのように解決するのですか?

まず最初に、Hot Module Replacement (HMR)はまだ実験的な機能であることをお知らせします。

HMRは、実行中のアプリケーションでモジュールを交換する(モジュールを追加・削除する)方法です。基本的には、全ページを再読み込みすることなく、変更されたモジュールを更新することができます。

ドキュメンテーション

前提条件

HMRにはあまり関係ないですが、リンクはこちらです。

これらの回答をドキュメントに追加しておきます。

どのように動作するのですか?

アプリビューから

アプリコードはHMRランタイムにアップデートを確認するよう依頼します。HMRランタイムはアップデートをダウンロードし(非同期)、アップデートが利用可能であることをアプリコードに伝える。アプリコードはHMRランタイムにアップデートを適用するように要求します。 HMRランタイムはアップデートを適用する(sync)。アプリコードはこのプロセスでユーザーのインタラクションを必要とするかしないか(あなたが決めること)。

コンパイラ(webpack)側から見た場合

通常のアセットに加えて、コンパイラは以前のバージョンからこのバージョンへのアップデートを可能にするために "Update" を発行する必要があります。この"Update"には、2つの部分があります。

  1. アップデートマニフェスト(json)
  2. 1つまたは複数のアップデートチャンク(js)

マニフェストには、新しいコンパイル ハッシュとすべてのアップデート チャンク (2) のリストが含まれています。

更新チャンクは、このチャンク内のすべての更新されたモジュールのコード(またはモジュールが削除された場合はフラグ)を含んでいます。

コンパイラはさらに、モジュールとチャンクの ID がこれらのビルドの間で一貫していることを確認します。これは、ビルド間でそれらを保存するために "records" json ファイルを使用します(または、メモリ内に保存します)。

モジュールビューから

HMRはopt-in機能なので、HMRのコードを含むモジュールにのみ影響します。ドキュメントには、モジュールで利用可能なAPIが記述されています。一般に、モジュール開発者は、このモジュールの依存関係が更新されたときに呼び出されるハンドラを書きます。また、このモジュールが更新されたときに呼び出されるハンドラも書くことができます。

ほとんどの場合、すべてのモジュールにHMRのコードを書くことは必須ではありません。もし、あるモジュールにHMRハンドラがなければ、更新は泡と消えます。つまり、1つのハンドラで完全なモジュールツリーの更新を処理することができるのです。このツリー内の単一のモジュールが更新されると、完全なモジュールツリーが再ロードされます(再ロードのみ、転送はされません)。

HMRランタイムビューより(技術的)

モジュールシステムのランタイムには、モジュールを追跡するための追加コードが発行されます。 parentschildren .

管理側では、ランタイムは2つのメソッドをサポートしている。 checkapply .

A check は、更新マニフェストへの HTTP リクエストを行います。この要求が失敗した場合、利用可能なアップデートはありません。それ以外の場合は、アップデートされたチャンクのリストと、現在ロードされているチャンクのリストが比較されます。ロードされた各チャンクについて、対応するアップデートチャンクがダウンロードされます。すべてのモジュール更新は更新としてランタイムに保存される。ランタイムは ready 状態であり、アップデートがダウンロードされ、適用できる状態にあることを意味します。

Ready 状態の新しいチャンク要求ごとに、アップデートチャンクもダウンロードされます。

は、その apply メソッドは、更新されたすべてのモジュールに無効のフラグを立てます。無効なモジュールには、そのモジュールに更新ハンドラ、もしくはすべての親に更新ハンドラが必要です。さもないと、invalid が泡となって出てきて、すべての親モジュールも invalid としてマークされます。このプロセスは、バブルアップが発生しなくなるまで続けられます。エントリポイントまでバブルアップすると、処理は失敗します。

ここで、すべての無効なモジュールは、ディスポーズされ(ディスポーズハンドラ)、アンロードされます。そして、現在のハッシュが更新され、すべての "accept" ハンドラが呼び出されます。ランタイムは 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 をエントリポイントとして使用します。そうでない場合は、HMRの管理コードとして checkapply .

ご意見をお聞かせください。何がそんなにかっこいいのか?

  • LiveReloadのようなものですが、あらゆる種類のモジュールのためのものです。
  • 本番で使える。
  • アップデートはコードスプリッティングを尊重し、アプリの使用部分のアップデートのみをダウンロードします。
  • アプリケーションの一部に使用することで、他のモジュールに影響を与えることはありません
  • HMRが無効の場合、すべてのHMRコードはコンパイラによって削除されます(ラップは if(module.hot) ).

注意事項

  • 実験的なもので、あまりテストされていない。
  • いくつかのバグを期待してください。
  • 理論的には本番で使えるが、本格的に使うには時期尚早かもしれない。
  • モジュールIDはコンパイル間で追跡する必要があるので、それを保存する必要があります( records ).
  • 最初のコンパイル以降、オプティマイザはモジュールIDをこれ以上最適化できない。バンドルサイズに少し影響します。
  • HMR ランタイムコードはバンドルサイズを増加させます。
  • 実運用では、HMRハンドラをテストするために、追加のテストが必要です。これはかなり難しいかもしれません。