Тема
Что такое Module Federation
Module Federation позволяет host-приложению загрузить и показать frontend, который был собран и опубликован отдельно.
- Host или shell — главное приложение страницы.
- Remote — подключаемый модуль, например billing или support.
- Mount — один запущенный экземпляр remote внутри DOM-контейнера.
Query Layer не загружает JavaScript remote. Этим занимается Webpack/Rspack/Vite federation plugin. Query Layer решает вопрос server state после загрузки remote: кто владеет cache, как remote создаёт stores и какие данные ему разрешены.
Когда MF нужен
Module Federation оправдан, если:
- команды выпускают части frontend независимо;
- remote имеет отдельную сборку и deployment;
- host подключает remote во время выполнения;
- нужен независимый rollback remote;
- границы предметных областей важнее простоты monolith-сборки.
Для одного frontend или обычной lazy route используйте стандартные stores без MF. Начните с быстрого старта.
Кто за что отвечает
| Задача | Host | Remote |
|---|---|---|
Загрузить remoteEntry.js | да | публикует файл |
| Выбрать DOM container | да | использует переданный container |
| Решить, когда mount/unmount | да, часто вместе с router | реализует mount() |
Создать root QueryRuntime | да | нет |
| Создать ограниченный scope | да | получает готовый scope |
| Определить tenant/user | да | не доверяет своим источникам |
| Создать предметные MobX stores | нет | да |
| Использовать Axios напрямую в UI | нет | нет |
| Освободить UI | вызывает unmount | возвращает disposer |
Откуда remote получает runtime
Ничего не передаётся автоматически. Host сам вызывает экспортированную функцию remote и передаёт зависимости обычным аргументом:
ts
const remote = await import("billing/bootstrap")
const billingScope = runtime.createParticipantScope({
// registration показан подробно дальше
})
const unmount = remote.mount({
container: document.getElementById("billing-root")!,
scope: billingScope,
api: billingApi,
})Router может отвечать за выбор route и момент вызова mount, но он не обязан «раздавать переменные». Composition-код host, который обрабатывает route, создаёт scope и передаёт его в mount.
Полный поток
mermaid
flowchart TD
Route["Host router открыл /billing"] --> Import["Host импортировал billing/bootstrap"]
Import --> Scope["Host создал billingScope"]
Scope --> Mount["Host вызвал remote.mount(options)"]
Mount --> Store["Remote создал domain stores"]
Store --> Facade["Stores используют scope facades"]
Facade --> Runtime["Host QueryRuntime"]scope — не глобальный объект, не Axios client и не root runtime. Это ограниченный набор factory-функций для одного mount remote.
Почему root runtime остаётся в host
Root умеет создавать любые participant scopes, читать общую диагностику и освобождать всё приложение. Remote такие административные права не нужны.
Host выдаёт только IScopedQueryRuntime, где доступны разрешённые:
scope.request;scope.fetch;scope.query;scope.mutation;scope.dispose().
Namespace permissions не позволят billing remote читать query support remote.
Порядок изучения
- Bootstrap и mount — что реально экспортирует remote.
- Настройка host и remote — federation plugin и shared packages.
- Runtime в host — откуда берётся root runtime.
- Как remote получает scope — полный typed contract.
- Основные понятия — participant, scope, partition.
- Capabilities — runtime promises и permissions remote.
- Фасады scope — все методы, доступные store layer.
- Кэш и sharing — private/shared query.
- Storage и lifecycle.
Не начинайте со scope.query.createStore, пока не понятна функция mount и место, где host передаёт scope remote.