Viteホットモジュール置換‐完全な例


Vililla JSプロジェクトのためにホットモジュール置換(HMR)を設定する方法について説明します.目標は、コードを変更したり、アプリケーションを再起動せずに変更を見ることができることです.
私にとって、これは特に私がシミュレーションを構築していて、私が生の変化をするので、状態を失いたくないとき、創造的なコーディングにおいて特に役に立ちます.

ここのこの記事の完全なソースコードhttps://github.com/OmarShehata/vite-hot-reload-example .

実装の概要


私はどのように新しいモジュールを有効にするために可能な限り簡単に私のHMRを設定して表示するつもりです.次のセクションでは、どのように動作するかを壊しますので、すべての警告を認識し、必要に応じてプロジェクトで使用できます.
HMRを任意のモジュールで有効にするには、イベントハンドラをファイルの先頭に追加します.
import { HMREventHandler } from './HotModuleReloadSetup.js';

if (import.meta.hot) {
  import.meta.hot.accept(HMREventHandler)
}
このモジュールが更新されるとき、これはVITEにページをさわやかにするのを避けて、代わりにHMRイベントを起こします.
次に、SingletonのインスタンスがありますHotModuleReloadSetup これは動的にインポートされたモジュールを受け取り、自動的にスワップアウトします.
import HotModuleReloadSetup from './HotModuleReloadSetup.js';
// Setup HMR
const hmr = new HotModuleReloadSetup();
// Load a module that will be updated dynamically
hmr.import(await import('./Draw.js'));
私は今、Drawクラスのインスタンスにアクセスできますhmr.instances['Draw'] .
最後に、DrawクラスはhotReload ハンドラ.すべての状態変数を新しいインスタンスにコピーできるように、これは古いインスタンスへのリファレンスを渡します.
それで、私が呼ぶときhmr.instances['Draw'].draw() Renderループでは、常に最新のコードを使用します.
このパターンはPlayCanvas does their hot reloading .

動作方法


ここでは、HMRモジュールの変更を行うときに何が起こるかですDraw.js 私の場合)
1 - VITEは、我々は、リスナーを経由してimport.meta.hot.accept )
2 -次に、その新しいモジュールを使ってDOMにカスタムイベントを送りますHotModuleReloadSetup.js ):
export function HMREventHandler(newModule) {
    const event = new CustomEvent('hot-module-reload', { detail: { newModule } });
    document.body.dispatchEvent(event);
}
これによりHotModuleReloadSetup 世界的にこれらのイベントを聞いてください.
3 -我々のマップを検索modules 受信した新しいモジュールが存在するかどうかを確認するには
4 -もしそうなら、新しいモジュール、呼び出しから新しいインスタンスを作成しますnewInstance.hotReload(oldInstance) , 古いモジュールと古いインスタンスを破棄する
swapModule(newModule) {
  const name = newModule.default.name;
  const oldModule = this.modules[name];
  const oldInstance = this.instances[name]
  if (!oldModule) return;

  const newInstance = new newModule.default();
  newInstance.hotReload(oldInstance)

  this.modules[name] = newModule
  this.instances[name] = newInstance
}
この方法では、常にinstances マップを使用するか、modules マップ.あなたのコードがクラス(多くの敵または弾丸のような)の多くのインスタンスを生んでいるならば、後者は使用されることができます、そして、あなたは生のコード変化が新しく生じたインスタンスに影響を及ぼして欲しいです.

警告

  • コードが変更されたときに更新されるクラスの複数のインスタンスを持つ必要がある場合、これらのインスタンスの配列を保持し、同じ方法でそれらをすべてスワップする必要がありますHotModuleReloadSetup.swapModule does
  • HMRクラスがコンストラクタ引数を必要とする場合は、グローバルインスタンスにそれらを格納する必要があります.
  • 関数名を書き換えるのではなく、このような動的インポートを使用すると、関数のすべての用途を更新できません.原因hmr.instances['Draw'].draw() 関数名がもうなくなりましたのでdraw 生産ビルドで.
  • モジュールを名前でインポートしてhmr.import() VITEでの動的インポートの制限により、https://github.com/rollup/plugins/tree/master/packages/dynamic-import-vars#limitations
  • 読書ありがとう!私はあなたが役に立つと思います.あなたがHMRを合理化するためにバグまたはより良い方法を見つけるならば、特に創造的なコーディングのために、私は聞きたいです.あなたはTwitterで私を見つけることができます.