Skip to content

Что такое 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. Начните с быстрого старта.

Кто за что отвечает

ЗадачаHostRemote
Загрузить 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.

Порядок изучения

  1. Bootstrap и mount — что реально экспортирует remote.
  2. Настройка host и remote — federation plugin и shared packages.
  3. Runtime в host — откуда берётся root runtime.
  4. Как remote получает scope — полный typed contract.
  5. Основные понятия — participant, scope, partition.
  6. Capabilities — runtime promises и permissions remote.
  7. Фасады scope — все методы, доступные store layer.
  8. Кэш и sharing — private/shared query.
  9. Storage и lifecycle.

Не начинайте со scope.query.createStore, пока не понятна функция mount и место, где host передаёт scope remote.