Замена модулей при запуске
Замена модулей при запуске (HMR) обменивает, добавляет или удаляет модули во время работы приложения без полной перезагрузки. Это может значительно ускорить разработку несколькими способами:
- Сохранение состояния приложения, которое теряется при полной перезагрузке.
- Экономия ценного времени разработки, обновляя только изменённые части.
- Немедленное обновление браузера при внесении изменений в CSS/JS в исходном коде, что практически сравнимо с изменением стилей непосредственно в инструментах разработчика браузера.
Как это работает
Давайте рассмотрим несколько различных точек зрения, чтобы понять, как работает HMR...
В приложении
Следующие шаги позволяют заменять модули в приложении:
- Приложение запрашивает у HMR-времени выполнения проверку обновлений.
- Время выполнения асинхронно загружает обновления и уведомляет приложение.
- Приложение запрашивает у времени выполнения применение обновлений.
- Время выполнения синхронно применяет обновления.
Вы можете настроить HMR так, чтобы этот процесс происходил автоматически, или вы можете потребовать взаимодействия пользователя для обновления.
В компиляторе
Помимо обычных ресурсов, компилятору необходимо сгенерировать "обновление", чтобы позволить обновление с предыдущей версии на новую. "Обновление" состоит из двух частей:
- Обновлённый манифест (JSON)
- Один или несколько обновлённых фрагментов (JavaScript)
Манифест содержит новый хеш компиляции и список всех обновлённых фрагментов. Каждый из этих фрагментов содержит новый код для всех обновлённых модулей (или флаг, указывающий на удаление модуля).
Компилятор гарантирует, что идентификаторы модулей и фрагментов остаются согласованными между сборками. Обычно он хранит эти идентификаторы в памяти (например, с помощью webpack-dev-server), но также возможно хранить их в JSON-файле.
В модуле
HMR — это опциональная функция, которая влияет только на модули, содержащие код HMR. Одним примером является исправление стилей через style-loader. Для работы исправления, style-loader реализует интерфейс HMR; при получении обновления через HMR, он заменяет старые стили новыми.
Аналогично, при реализации интерфейса HMR в модуле, вы можете описать, что должно произойти при обновлении модуля. Однако в большинстве случаев писать код HMR в каждом модуле необязательно. Если модуль не имеет обработчиков HMR, обновление распространяется вверх. Это означает, что один обработчик может обновить всю иерархию модулей. Если обновляется один модуль из иерархии, перегружается весь набор зависимостей.
Подробную информацию об интерфейсе module.hot см. на странице API HMR.
В времени выполнения
Здесь всё становится немного сложнее… если вы не заинтересованы во внутренних деталях, можете перейти к странице API HMR или руководству по HMR.
Для времени выполнения системы модулей генерируется дополнительный код для отслеживания модулей parents и children. Со стороны управления время выполнения поддерживает два метода: check и apply.
check делает HTTP-запрос к манифесту обновления. Если этот запрос не удаётся, доступных обновлений нет. Если он успешно выполняется, список обновлённых фрагментов сравнивается со списком загруженных фрагментов. Для каждого загруженного фрагмента загружается соответствующий фрагмент обновления. Все обновления модулей сохраняются в времени выполнения. Когда все фрагменты обновлений загружены и готовы к применению, время выполнения переключается в состояние ready.
Метод apply помечает все обновлённые модули как недействительные. Для каждого недействительного модуля должен быть обработчик обновления в модуле или его предке(ах). В противном случае флаг недействительности распространяется вверх и делает недействительными предков. Каждое распространение продолжается до точки входа приложения или модуля с обработчиком обновления (что произойдёт раньше). Если распространение доходит до точки входа, процесс завершается неудачей.
После этого все недействительные модули удаляются (через обработчик удаления) и разгружаются. Текущий хеш обновляется, и вызываются все обработчики accept. Время выполнения переключается обратно в состояние idle и всё продолжает работать как обычно.
Начало работы
HMR можно использовать в разработке как замену LiveReload. webpack-dev-server поддерживает режим hot, в котором он пытается обновить с помощью HMR перед попыткой перезагрузки всей страницы. Подробную информацию см. в руководстве Замена модулей при запуске.
© JS Foundation and other contributors
Licensed under the Creative Commons Attribution License 4.0.
https://webpack.js.org/concepts/hot-module-replacement