#инструменты #JS #Лаборатория_веб_платформы
Посмотрим детали реализации.
Всю служебную инфу о модуле будем записывать в специальном объекте import.meta.
Самое первое, что нужно, это пометка, участвует ли модуль в HMR-процессе. Это объект
import.meta.hot:
let test = 1;
//...
if (import.meta.hot) {
// в этот условии записывается вся начинка HMR
// нужная только для режима разработки
}
Всё, что сборщик встретит внутри таких условий в модулях, он будет использовать только в режиме разработки. При билде для продашкена все эти места будут выпилены.
Внутри
import.meta.hot есть несколько методов, которые будут вызываться на этапах «жизни» HMR-модуля и свойств.import.meta.hot.accept — этот метод, который в старом модуле принимает подменённый новый модуль.
import.meta.hot.accept(({ module }) => { // module – новый импортированный модуль
value = module.value;
});
При замене нужно сменить переменные в экспортирующих частях модуля со старого на новый модуль.
import.meta.hot.dispose — этот метод, который в старом модуле запускается перед подключением нового модуля, чтобы подчистить в старом необходимые штуки (отключить стили, снять обработчики событий).
import.meta.hot.dispose(() => {
document.head.removeChild(style);
});
import.meta.hot.decline — это метод для того, чтобы модуль мог безусловно отклонить HMR-обновление. Этот метод триггерит полную перезагрузку страницы. Он нужнен, например, в случае, если модуль вносит в состояние приложения какие-то непоправимые сайд-эффекты.
import.meta.hot.decline();
import.meta.hot.invalidate — это метод для того, чтобы по условию пометить модуль как нуждающийся в обновлении и стриггерить перезагрузку страницы.
import.meta.hot.accept(({ module }) => {
if (something) {
import.meta.hot.invalidate();
}
});
import.meta.hot.data — «буфер» для передачи данных между обновлением модулей (к нему можно обращаться между dispose() и accept()).
if (import.meta.hot) {
// Приём данных от прошлого dispose
import.meta.hot.accept(({ module }) => {
value = import.meta.hot.data.value || module.value;
});
// Отправка данных будущему accept
import.meta.hot.dispose(() => {
import.meta.hot.data = { value };
});
}
Важное дополнение про ES-модули. Так как ES-модули не поддерживают неотносительные пути при подключении —
import {init} from 'module', то на первом этапе «сборки» нужно для дев-режима автоматически пройтись по всем файлам и заменить пути импортов на относительные import {init} from '/node_modules/module'.