Как организовать общение между микрофронтендами?
Что проверяют
Понимаете ли вы, что микрофронтенды затевают ради независимости команд, и общение между ними не должно эту независимость разрушать. Интервьюер ждёт не список способов, а критерий выбора. Следом часто спрашивают, как делить состояние авторизации и что делать, если событие пришло раньше, чем подписчик загрузился.
Как отвечать
Начните с принципа: чем меньше микрофронтенды знают друг о друге, тем лучше, а всё общение идёт через явный контракт. Дальше способы от слабой связанности к сильной:
- URL: маршрут и query-параметры как общее состояние. Переживает перезагрузку и читается любым приложением;
- данные от оболочки: хост при монтировании передаёт пропсы и колбэки. В single-spa это
customProps, у веб-компонентов атрибуты, свойства и DOM-события; - события в браузере:
CustomEventнаwindowили на отдельномEventTarget, имена с префиксом команды (cart:item-added), типы полезной нагрузки в общем npm-пакете с версией; - общий модуль через Module Federation: маленький сервис вроде
authServiceили шины событий, объявленный вsharedсsingleton: true. Работает в webpack 5, Rspack и через плагин для Vite; postMessageиBroadcastChannel: для микрофронтендов в iframe и для синхронизации между вкладками;- бэкенд как источник правды: бизнесовые данные каждый читает из API, а не получает от соседа.
Отдельно скажите про запоздавших подписчиков: событие, отправленное до загрузки соседа, теряется. Выход в том, чтобы хранить последнее значение и отдавать его при подписке или передавать состояние вместо событий.
Где спотыкаются
Предлагают один общий Redux-стор на все приложения. Это возвращает монолит, только распределённый: любой рефакторинг стора ломает соседей.
Заводят события без контракта и без версий. Одна команда переименовала поле в detail, у другой молча сломалась корзина.
Не снимают обработчики при размонтировании. После нескольких переходов между приложениями подписчиков становится несколько, и одно событие обрабатывается трижды.