CC 4.0 ライセンス

このセクションの内容は、以下のリンクの内容から派生したものであり、CC BY 4.0 ライセンスの対象となります。

以下の内容は、特に明記されていない限り、元のコンテンツに基づいて変更および削除された結果であると想定できます。

ホットモジュール置換

通常、ユーザーはインターフェースがアクセス可能かどうかを確認してから、作業を開始します。例として、更新されたモジュールを`accept`する方法を以下に示します。

if (module.hot) {
  module.hot.accept('./library.js', function () {
    // Do something with the updated library module...
  });
}

// or
if (import.meta.webpackHot) {
  import.meta.webpackHot.accept('./library.js', function () {
    // Do something with the updated library module…
  });
}

以下のメソッドがサポートされています...

モジュール API

accept

指定された`dependencies`の更新を受け入れ、それらの更新に反応するための`callback`を実行します。さらに、オプションのエラーハンドラを添付することもできます。

module.hot.accept(
  dependencies, // Either a string or an array of strings
  callback, // Function to fire when the dependencies are updated
  errorHandler, // (err, {moduleId, dependencyId}) => {}
);

// or
import.meta.webpackHot.accept(
  dependencies, // Either a string or an array of strings
  callback, // Function to fire when the dependencies are updated
  errorHandler, // (err, {moduleId, dependencyId}) => {}
);

ESM`import`を使用する場合、`dependencies`からインポートされたすべてのシンボルは自動的に更新されます。注:依存関係文字列は、`import`の`from`文字列と正確に一致する必要があります。場合によっては、`callback`を省略することもできます。ここで`callback`内で`require()`を使用しても意味がありません。

CommonJSを使用する場合は、`callback`内で`require()`を使用して依存関係を手動で更新する必要があります。ここで`callback`を省略することは意味がありません。

acceptのエラーハンドラ

(err, {moduleId, dependencyId}) => {}

  • `err`:2番目の引数のコールバック、またはESM依存関係を使用する場合の依存関係の実行中にスローされたエラー。
  • `moduleId`:現在のモジュールID。
  • `dependencyId`:変更された(最初の)依存関係のモジュールID。

accept (self)

自身の更新を受け入れる。

module.hot.accept(
  errorHandler, // Function to handle errors when evaluating the new version
);

// or
import.meta.webpackHot.accept(
  errorHandler, // Function to handle errors when evaluating the new version
);

このモジュールまたは依存関係が更新されると、このモジュールは親に通知することなく破棄および再評価できます。このモジュールにエクスポートがない(またはエクスポートが別の方法で更新される)場合、これは理にかなっています。

このモジュール(または依存関係)の評価が例外をスローした場合、`errorHandler`が起動されます。

自己受入のエラーハンドラ

(err, {moduleId, module}) => {}

  • `err`:新しいバージョンの評価時のエラー。
  • `moduleId`:現在のモジュールID。
  • `module`:現在のモジュールインスタンス。
    • `module.hot`:エラーが発生したモジュールインスタンスのHMR APIの使用を許可します。一般的なシナリオは、再び自己受入することです。また、破棄ハンドラーを追加してデータを渡すことも理にかなっています。エラーが発生したモジュールは既に部分的に実行されている可能性があるため、矛盾した状態にならないように注意してください。`module.hot.data`を使用して部分的な状態を格納できます。
    • `module.exports`:上書きできますが、プロダクションモードではプロパティ名が変更される可能性があるため、注意してください。

decline

指定された`dependencies`の更新を拒否し、更新が`'decline'`コードで失敗するようにします。

module.hot.decline(
  dependencies, // Either a string or an array of strings
);

// or
import.meta.webpackHot.decline(
  dependencies, // Either a string or an array of strings
);

依存関係を更新不可としてフラグ付けします。これは、この依存関係のエクスポートの変更を処理できない場合、または処理がまだ実装されていない場合に意味があります。HMR管理コードによっては、これらの依存関係(またはその受け入れられていない依存関係)の更新により、通常、ページが完全にリロードされます。

decline (self)

自身の更新を拒否する。

module.hot.decline();

// or
import.meta.webpackHot.decline();

このモジュールを更新不可としてフラグ付けします。これは、このモジュールに不可逆的な副作用がある場合、またはこのモジュールにHMR処理がまだ実装されていない場合に意味があります。HMR管理コードによっては、このモジュール(または受け入れられていない依存関係)の更新により、通常、ページが完全にリロードされます。

dispose (または addDisposeHandler)

現在のモジュールコードが置き換えられたときに実行されるハンドラーを追加します。これは、要求または作成した永続リソースを削除するために使用する必要があります。状態を更新されたモジュールに転送する場合は、指定された`data`パラメータに追加します。このオブジェクトは、更新後に`module.hot.data`で使用できるようになります。

module.hot.dispose(data => {
  // Clean up and pass data to the updated module...
});

// or
import.meta.webpackHot.dispose(data => {
  // Clean up and pass data to the updated module...
});

invalidate

このメソッドを呼び出すと、現在のモジュールが無効になり、HMR更新が適用されるときに破棄して再作成されます。これは、このモジュールの通常の更新のようにバブルアップします。 `invalidate`はこのモジュールによって自己受入できません。

`idle`状態の間に呼び出されると、このモジュールを含む新しいHMR更新が作成されます。HMRは`ready`状態になります.

`ready`または`prepare`状態の間に呼び出されると、このモジュールは現在のHMR更新に追加されます。

`check`状態の間に呼び出されると、更新が利用可能な場合、このモジュールは更新に追加されます。更新がない場合は、新しい更新が作成されます。HMRは`ready`状態になります。

`dispose`または`apply`状態の間に呼び出されると、HMRはこれらの状態から抜け出した後にそれをピックアップします。

ユースケース

条件付き受入

モジュールは依存関係を受け入れることができますが、依存関係の変更が処理できない場合は`invalidate`を呼び出すことができます。

import { x, y } from './dep';
import { processX, processY } from 'anotherDep';

const oldY = y;

processX(x);
export default processY(y);

module.hot.accept('./dep', () => {
  if (y !== oldY) {
    // This can't be handled, bubble to parent
    module.hot.invalidate();
    return;
  }
  // This can be handled
  processX(x);
});

条件付き自己受入

モジュールは自身を自己受入できますが、変更が処理できない場合は自身を無効にすることができます。

const VALUE = 'constant';

export default VALUE;

if (
  module.hot.data &&
  module.hot.data.value &&
  module.hot.data.value !== VALUE
) {
  module.hot.invalidate();
} else {
  module.hot.dispose(data => {
    data.value = VALUE;
  });
  module.hot.accept();
}

カスタムHMR更新のトリガー

const moduleId = chooseAModule();
const code = __webpack_modules__[moduleId].toString();
__webpack_modules__[moduleId] = eval(`(${makeChanges(code)})`);
if (require.cache[moduleId]) {
  require.cache[moduleId].hot.invalidate();
  module.hot.apply();
}

T> `invalidate`が呼び出されると、`dispose`ハンドラが最終的に呼び出され、`module.hot.data`が入力されます。`dispose`ハンドラが登録されていない場合は、空のオブジェクトが`module.hot.data`に提供されます。

W> `invalidate`を何度も呼び出すことによって、`invalidate`ループに陥らないでください。これはスタックオーバーフローを引き起こし、HMRが`fail`状態になります。

removeDisposeHandler

`dispose`または`addDisposeHandler`を介して追加されたハンドラを削除します。

module.hot.removeDisposeHandler(callback);

// or
import.meta.webpackHot.removeDisposeHandler(callback);

管理 API

status

ホットモジュール置換プロセスの現在のステータスを取得します。

module.hot.status(); // Will return one of the following strings...

// or
import.meta.webpackHot.status();
ステータス 説明
idle プロセスは`check`の呼び出しを待機しています。
check プロセスは更新を確認しています.
prepare プロセスは更新の準備をしています(例:更新されたモジュールのダウンロード)。
ready 更新が準備され、利用可能です.
dispose プロセスは、置き換えられるモジュールで`dispose`ハンドラを呼び出しています.
apply プロセスは`accept`ハンドラを呼び出し、自己受入モジュールを再実行しています。
abort 更新は中止されましたが、システムは依然として以前の状態です.
fail 更新で例外が発生し、システムの状態が損なわれました.

check

ロードされたすべてのモジュールに更新があるかどうかをテストし、更新がある場合は`apply`します。

module.hot
  .check(autoApply)
  .then(outdatedModules => {
    // outdated modules...
  })
  .catch(error => {
    // catch errors
  });

// or
import.meta.webpackHot
  .check(autoApply)
  .then(outdatedModules => {
    // outdated modules...
  })
  .catch(error => {
    // catch errors
  });

`autoApply`パラメータは、ブール値または呼び出されたときに`apply`メソッドに渡す`options`にすることができます。

apply

更新プロセスを続行します(`module.hot.status() === 'ready'`である限り)。

module.hot
  .apply(options)
  .then(outdatedModules => {
    // outdated modules...
  })
  .catch(error => {
    // catch errors
  });

// or
import.meta.webpackHot
  .apply(options)
  .then(outdatedModules => {
    // outdated modules...
  })
  .catch(error => {
    // catch errors
  });

オプションの`options`オブジェクトには、次のプロパティを含めることができます。

  • `ignoreUnaccepted`(ブール値):受け入れられていないモジュールに加えられた変更を無視します。
  • `ignoreDeclined`(ブール値):拒否されたモジュールに加えられた変更を無視します。
  • ignoreErrored (boolean): accept ハンドラ、エラーハンドラ、およびモジュールの再評価中にスローされたエラーを無視します。
  • onDeclined (function(info)): 拒否されたモジュールの通知関数
  • onUnaccepted (function(info)): 受け入れられなかったモジュールの通知関数
  • onAccepted (function(info)): 受け入れられたモジュールの通知関数
  • onDisposed (function(info)): 破棄されたモジュールの通知関数
  • onErrored (function(info)): エラーの通知関数

info パラメータは、以下の値の一部を含むオブジェクトになります。

{
  type: 'self-declined' | 'declined' |
        'unaccepted' | 'accepted' |
        'disposed' | 'accept-errored' |
        'self-accept-errored' | 'self-accept-error-handler-errored',
  moduleId: 4, // The module in question.
  dependencyId: 3, // For errors: the module id owning the accept handler.
  chain: [1, 2, 3, 4], // For declined/accepted/unaccepted: the chain from where the update was propagated.
  parentId: 5, // For declined: the module id of the declining parent
  outdatedModules: [1, 2, 3, 4], // For accepted: the modules that are outdated and will be disposed
  outdatedDependencies: { // For accepted: The location of accept handlers that will handle the update
    5: [4]
  },
  error: new Error(...), // For errors: the thrown error
  originalError: new Error(...) // For self-accept-error-handler-errored:
                                // the error thrown by the module before the error handler tried to handle it.
}

addStatusHandler

status の変更をリッスンする関数を登録します。

module.hot.addStatusHandler(status => {
  // React to the current status...
});

// or
import.meta.webpackHot.addStatusHandler(status => {
  // React to the current status...
});

ステータスハンドラが Promise を返す場合、HMR システムは処理を続行する前に Promise が解決されるのを待ちますのでご注意ください。

removeStatusHandler

登録済みのステータスハンドラを削除します。

module.hot.removeStatusHandler(callback);

// or
import.meta.webpackHot.removeStatusHandler(callback);