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

18 февраля 2025 г.Будни разработчика
Сказ о том, как я Hot Module Reload в секьюрном iframe настраивал. | 🔁 Новости из телеграм - Ghostbase News

#заметка дня

Сказ о том, как я 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.

Итак, в чём же сложности?

  1. Для начала, в Google Sheets нужно передать адрес, по которому будут грузиться данные. Нет, просто localhost нельзя, нужно сохранять возможность поделиться dev-средой, как обычной таблицец. Решение — туннели (вроде ngrok) с прокидыванием локального домена (try_files в nginx) прямо к файлам сборки.

  2. Естественно, данные должны грузиться секьюрно, по https. Но, к счастью, туннели это решают.

  3. Не всем разработчикам в компании нужен HMR, им достаточно и простой dev-сборки.

А вот что туннели решали с трудом — это прокидывание WebSocket-соединения. Я никак не мог понять, как же правильно поднять одновременно https и туннель, чтобы браузер не ругался на несекьюрный источник.

И тут до меня дошло: localhost же у нас по-соглашению всегда секьюрный. Поднимать на нём https не имеет смысла.

Но был нюанс: если прописать localhost в конфиге webpack-dev-server (а Rspack использует именно его), то он просто... исчезал из урла. Растворялся. И указывал на текущую страницу. Что, конечно, меня не устраивало.

К счастью, решилось старым добрым 127.0.0.1.

В остальном же проблем не возникло: HMR прекрасно настроился по официальной документации с React Fast Refresh и получился следующий конфиг:

  1. Три режима среды сборки: dev, none и production. Под none подразумевается дев-билд, без запуска сервера.

  2. Туннели прокинуты до каталога build внутри репозитория и предоставляют доступ из открытого интернета по кастомному домену, с https на http.

  3. webpack-dev-server настроен таким образом, что чанки с обновлениями сохраняются на диск и таким способом доставляются по адресу этого же тоннеля. Формат имён одинаков для сред dev и none.

  4. CORS отключён ('Access-Control-Allow-Origin': '*'), и это пока мне не очень нравится.

  5. WebSocket-соединение просто запущено на 127.0.0.1.

Таким образом, получился отличный универсальный способ. Все разработчики компании просто могут запустить локальный билд без необходимости в HMR. А те, кому надо — запускают yarn dev и больше никакой дополнительной конфигурации не требуется. А главное, за счёт скорости работы Rspack я могу смело указать несколько точек входа (entrypoints) и запускать независимые друг от друга части продукта с сохранением горячей перезагрузки.

Да, немного сумбурно вышло, и большинству такое в жизни не пригодится. Но если вдруг у вас возникнет такая же необходимость шарить dev-среду проекта наружу в открытую сеть — вы знаете, что делать.

#rspack #webpack #hmr