Spec-Zone.ru › webpack 5

Замена модулей при горячей перезагрузке

Если Замена модулей при горячей перезагрузке включена через HotModuleReplacementPlugin, её интерфейс будет доступен через свойство module.hot, а также свойство import.meta.webpackHot. Обратите внимание, что только import.meta.webpackHot может использоваться в строгом ESM.

Обычно пользователи проверяют доступность интерфейса, а затем начинают с ним работать. Например, вот как можно 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 автоматически обновляются. Примечание: строка зависимости должна точно соответствовать строке from в import. В некоторых случаях callback можно опустить. Использование require() в callback здесь не имеет смысла.

При использовании CommonJS необходимо вручную обновить зависимости, используя require() в callback. Опускание callback здесь не имеет смысла.

errorHandler для accept

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

  • err: ошибка, брошенная обратным вызовом во втором аргументе или во время выполнения зависимостей при использовании ESM-зависимостей.
  • moduleId: текущий идентификатор модуля.
  • dependencyId: идентификатор модуля (первой) изменённой зависимости.

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 срабатывает, когда при оценке этого модуля (или зависимостей) возникает исключение.

errorHandler для self accept

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

  • err: ошибка при оценке новой версии.
  • moduleId: текущий идентификатор модуля.
  • module: текущий экземпляр модуля.
    • module.hot: позволяет использовать 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
);

Помечает зависимость как не подлежащую обновлению. Это имеет смысл, когда изменения экспортов этой зависимости не могут быть обработаны или обработка ещё не реализована. В зависимости от вашего кода управления горячей перезагрузкой, обновление этих зависимостей (или не принятых зависимостей) обычно приводит к полной перезагрузке страницы.

decline (self)

Отклоняет обновления для себя.

module.hot.decline();

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

Помечает этот модуль как не подлежащий обновлению. Это имеет смысл, когда у этого модуля есть необратимые побочные эффекты или обработка горячей перезагрузки для этого модуля ещё не реализована. В зависимости от вашего кода управления горячей перезагрузкой, обновление этого модуля (или не принятых зависимостей) обычно приводит к полной перезагрузке страницы.

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

Вызов этого метода делает текущий модуль недействительным, что приводит к его удалению и повторному созданию при применении обновления горячей перезагрузки. Это распространяется, как и обычное обновление этого модуля. invalidate не может быть самопринятым этим модулем.

При вызове в состоянии idle, будет создано новое обновление горячей перезагрузки, содержащее этот модуль. Горячая перезагрузка перейдёт в состояние ready.

При вызове в состоянии ready или prepare, этот модуль будет добавлен в текущее обновление горячей перезагрузки.

При вызове в состоянии check, этот модуль будет добавлен в обновление при наличии обновления. Если обновление недоступно, будет создано новое обновление. Горячая перезагрузка перейдёт в состояние ready.

При вызове в состояниях dispose или apply, горячая перезагрузка подхватит его после выхода из этих состояний.

Примеры использования

Условное принятие

Модуль может принять зависимость, но может вызвать 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();
}

Вызов пользовательских обновлений горячей перезагрузки

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();
}
Подсказка

Когда вызывается invalidate, обработчик dispose будет в конечном итоге вызван и заполнит module.hot.data. Если обработчик dispose не зарегистрирован, пустой объект будет передан module.hot.data.

Предупреждение

Не попадайте в цикл invalidate вызывая invalidate снова и снова. Это приведёт к переполнению стека и переходу горячей перезагрузки в состояние 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 может быть булевым значением или options для передачи методу apply при вызове.

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 (булево): Игнорировать ошибки, возникшие в обработчиках accept, обработчиках ошибок и при повторной оценке модуля.
  • onDeclined (функция(информация)): Уведомление для отклоненных модулей
  • onUnaccepted (функция(информация)): Уведомление для не принятых модулей
  • onAccepted (функция(информация)): Уведомление для принятых модулей
  • onDisposed (функция(информация)): Уведомление для удалённых модулей
  • onErrored (функция(информация)): Уведомление об ошибках

Параметр 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, система горячей перезагрузки будет ждать, пока Promise разрешится, прежде чем продолжить.

removeStatusHandler

Удаляет зарегистрированный обработчик состояния.

module.hot.removeStatusHandler(callback);

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

© JS Foundation and other contributors
Licensed under the Creative Commons Attribution License 4.0.
https://webpack.js.org/api/hot-module-replacement

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API