Тема
Основные понятия Module Federation
Эта страница собирает термины после того, как понятны bootstrap, host runtime и передача scope.
QueryRuntime
Root-контейнер server state, которым владеет host:
ts
const runtime = createQueryRuntime(config)
await runtime.initialize()Он содержит общий QueryClient, request executor, browser lifecycle и реестр participants. Remote root runtime не получает.
Participant
Participant — один подключённый consumer runtime:
- host application;
- standalone application;
- один mount remote.
Один и тот же remote, смонтированный два раза, создаёт два participants.
Participant registration
Registration — объект, которым host описывает participant до создания scope:
ts
const registration = {
participantId: "billing-remote",
participantType: "remote",
version: "1.6.0",
minimumRuntimeVersion: "3.2.0",
requiredRuntimeCapabilities: ["query", "mutation"],
tenantId: session.tenantId,
userId: session.userId,
capabilities: {
queryNamespaces: [["billing"]],
mutationNamespaces: ["billing"],
},
} as constHost, а не remote, формирует final registration. Особенно это относится к tenantId, userId и namespace permissions.
Scope
scope — произвольное имя локальной переменной:
ts
const scope = runtime.createParticipantScope(registration)Можно назвать её billingScope или participantRuntime. Тип — IScopedQueryRuntime.
Scope:
- создаёт MobX stores на общей инфраструктуре host;
- автоматически добавляет owner/tenant/user partition;
- проверяет query и mutation namespaces;
- отслеживает созданные stores;
- освобождает их одним
scope.dispose().
Scope не является:
- Axios client;
- React context;
- MobX-store бизнес-модели;
- root QueryRuntime;
- глобальной переменной;
- механизмом загрузки remote.
Identity scope
После создания доступно scope.identity:
| Поле | Источник | Смысл |
|---|---|---|
participantId | registration | Стабильное имя модуля. |
participantType | registration | application, host или remote. |
version | registration | Версия модуля. |
tenantId, userId | host session | Data partition. |
instanceId | runtime или registration | Уникальный id конкретного mount. |
protocolVersion | runtime | Согласованная версия protocol. |
participantId может совпадать у двух mount. instanceId должен отличаться.
Логический и физический queryKey
Remote пишет логический ключ:
ts
;["billing", "invoices"]Runtime добавляет физический prefix, который концептуально содержит:
text
runtime application + tenant + user + private/shared owner + logical keyRemote не должен строить этот prefix вручную. Поэтому одинаковые логические ключи разных users и private mount не сталкиваются.
Namespace
Namespace — разрешённый префикс логического key.
ts
queryNamespaces: [["billing"], ["shared", "currency"]]Ключ ["billing", "invoices"] разрешён. Ключ ["support", "tickets"] запрещён.
Mutation namespace — строковый prefix:
ts
mutationNamespaces: ["billing"]Разрешены billing.pay и billing.cancel, запрещён support.close.
Private query
По умолчанию query принадлежит конкретному instanceId. Два mount billing remote с одинаковым логическим ключом получают разные cache entries.
Это безопасный default для screen state и персональных данных одного mount.
Shared query
Host может явно разрешить префикс в sharedQueryNamespaces:
ts
sharedQueryNamespaces: [["shared", "currency"]]Тогда participants одной application/tenant/user partition используют одну cache entry. Shared query обязана иметь definitionId:
ts
scope.query.createStore({
definitionId: "currency.dictionary.v1",
queryKey: () => ["shared", "currency", "list"],
queryFn: ({ signal }) => api.currency({ signal }),
})definitionId задаёт стабильный id такого договора. Runtime требует его наличие для shared query. FetchStore, QueryStore и InfiniteQueryStore передают id в query definition/observer, поэтому несовместимый definitionId для того же физического cache slot приводит к QueryDefinitionConflictError.
Runtime capabilities и participant capabilities
Это два разных понятия:
| Вид | Пример | Вопрос |
|---|---|---|
| Runtime capabilities | query, mutation | Какие части scoped API host вообще умеет предоставить? |
| Participant capabilities | query/mutation namespaces | С какими данными конкретному remote разрешено работать? |
Полная страница: Capabilities.
Data partition
Комбинация application, tenant и user определяет логический раздел данных. Shared query разделяется только внутри одной partition. Query пользователя A не становится доступной пользователю B.
Подробнее: Кэш, разделы и sharing.
Ownership и dispose
Store, созданный через scope, регистрируется как ресурс participant:
ts
const invoices = scope.query.createStore(...)Можно вызвать invoices.dispose() локально. При unmount host всё равно вызывает scope.dispose(), чтобы освободить оставшиеся stores и owned requests.
Root runtime.dispose() закрывает все ещё живые scopes. Правильный порядок: Lifecycle.