TGViewer
Виталий и Платформа Виталий и Платформа @web_platform · 1.81K subscribers
Post #16 165
Hot Module Replacement на нативных ES-модулях, часть 2

#инструменты #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'.
More from @web_platform
  1. Aug 14, 2026Мой воркфлоу с ИИшками сейчас У меня счас несколько подписок: • антропик 20$ (для разработ…
  2. Jul 13, 2026Hermes vs OpenClaw В комметах к прошлому посту @fogrew спросил, чем Hermes отличается от O…
  3. Jul 8, 2026Недавний инцидент с ДЦ сподвиг меня причесать всё на VPS с ботом-дайджестёром. Раньше было…
  4. Jul 2, 2026вчера мой ботик @web_platform_pulse_bot не прислал новости, а всё потому что кукольный теа…
  5. Jun 22, 2026btw там интересная система в репе, используются git submodules: в .gitmodules указывается…
  6. Jun 22, 20264 мая -> 20 июня, столько провисел мой pr в zed до мерджа зато теперь тема superset доступ…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →