Сказ о том, как я Hot Module Reload в секьюрном iframe настраивал.

#заметка дня
Сказ о том, как я Hot Module Reload в секьюрном iframe настраивал.
Итак, если вы на канале достаточно давно, то можете вспомнить, что продукт, над которым я работаю — это расширение для Google Sheets и работает оно в iframe. Довольно таки огороженном iframe.
Ну как, огороженном... Там довольно странная система из четырёх вложенных iframe, каждый из которых имеет довольно жёсткие скоупы.
И в итоге, такая простая вещь как Live Reload оказалась мне попросту недоступна! Любая попытка сделать window.location.reload() не то чтобы по команде из Live Server-решения, но даже по кнопке — приводила к краху iframe и, соответственно, продукта.
Оставался только один вариант — Hot Module Replacement. Да, горячая перезагрузка компонентов с нами уже несколько лет, но для легаси-проектов это достаточно проблематично. И хоть я уже 2 года как перелез на https://rspack.dev/ (и дико доволен), использовать на полную катушку не выходило.
Что я делал? А я запускал куски продукта в песочницах. Набрасывал моки и запускал блоки компонентов как обычное SPA-приложение. Не очень удобно? Не то слово. Зато очень быстро и легко покрывается тестами — потому что все моки уже на месте. Сплошные плюсы.
Но при работе в команде это всё максимально неудобно. В итоге всё же пришлось разбираться с HMR.
Итак, в чём же сложности?
-
Для начала, в Google Sheets нужно передать адрес, по которому будут грузиться данные. Нет, просто localhost нельзя, нужно сохранять возможность поделиться dev-средой, как обычной таблицец. Решение — туннели (вроде ngrok) с прокидыванием локального домена (try_files в nginx) прямо к файлам сборки.
-
Естественно, данные должны грузиться секьюрно, по https. Но, к счастью, туннели это решают.
-
Не всем разработчикам в компании нужен HMR, им достаточно и простой dev-сборки.
А вот что туннели решали с трудом — это прокидывание WebSocket-соединения. Я никак не мог понять, как же правильно поднять одновременно https и туннель, чтобы браузер не ругался на несекьюрный источник.
И тут до меня дошло: localhost же у нас по-соглашению всегда секьюрный. Поднимать на нём https не имеет смысла.
Но был нюанс: если прописать localhost в конфиге webpack-dev-server (а Rspack использует именно его), то он просто... исчезал из урла. Растворялся. И указывал на текущую страницу. Что, конечно, меня не устраивало.
К счастью, решилось старым добрым 127.0.0.1.
В остальном же проблем не возникло: HMR прекрасно настроился по официальной документации с React Fast Refresh и получился следующий конфиг:
-
Три режима среды сборки: dev, none и production. Под none подразумевается дев-билд, без запуска сервера.
-
Туннели прокинуты до каталога build внутри репозитория и предоставляют доступ из открытого интернета по кастомному домену, с https на http.
-
webpack-dev-server настроен таким образом, что чанки с обновлениями сохраняются на диск и таким способом доставляются по адресу этого же тоннеля. Формат имён одинаков для сред dev и none.
-
CORS отключён ('Access-Control-Allow-Origin': '*'), и это пока мне не очень нравится.
-
WebSocket-соединение просто запущено на 127.0.0.1.
Таким образом, получился отличный универсальный способ. Все разработчики компании просто могут запустить локальный билд без необходимости в HMR. А те, кому надо — запускают yarn dev и больше никакой дополнительной конфигурации не требуется. А главное, за счёт скорости работы Rspack я могу смело указать несколько точек входа (entrypoints) и запускать независимые друг от друга части продукта с сохранением горячей перезагрузки.
Да, немного сумбурно вышло, и большинству такое в жизни не пригодится. Но если вдруг у вас возникнет такая же необходимость шарить dev-среду проекта наружу в открытую сеть — вы знаете, что делать.
#rspack #webpack #hmr