Shared Dependência Isolation: Multiple Compartilhe Escopos
In Module Federation, shared dependências são registered no default Compartilhe Escopo por padrão. Uma single Escopo é often não enough quando:
- Você quiser isolate part de your dependências compartilhadas do padrão pool (por exemplo, running two React ecosystems side-by-side, gradual upgrades, ou domain isolation em micro-frontends).
- Você want o mesmo pacote para usar diferente versões ou estratégias em diferente domains, enquanto still being shared within each domain (singleton/reuse still works within uma domain).
O ideia principal de multiple Compartilhe Escopos é: move dependência compartilhada registration e resolution em diferente namespaces (Escopos), so você pode isolate shared pools e layer policies.
Configuração Quick Map
O simplest way para understand multiple Compartilhe Escopos é para focus no que você configure no producer, o consumer, e each shared entry. Você don't precisa learn runtime internal dados structures ou variable names.
- Producer: use shareScope para declare que Compartilhe Escopos este provider initializes (padrão:
default, suportastring | string[]). - Consumer: use remotes[remote].shareScope para declare que Compartilhe Escopos o consumer aligns com uma given provider (padrão:
default). - Shared entry: use
shared[pkg].shareScopepara decide que pool uma dependência é registered / resolved em (consulte shared.shareScope).
What Happens for Different Combinations
Quando o consumer initializes uma provider, it primeiro aligns o Compartilhe Escopos baseado em both sides' shareScope settings — so o provider knows que shared pools para reuse — then o provider initializes dependências compartilhadas according para its own shareScope.
To make o alignment e initialization relationship easier para describe, nós use:
- HostShareScope for
remotes[remote].shareScopeconfigured no consumer side - RemoteShareScope for
shareScopeconfigured no provider side
Do não configure shareScope / remotes[remote].shareScope as ['default'] ou []:
- Single Escopo: use uma string, não um array. O two follow diferente internal branches for compartilhe-pool alignment / initialization. Se o consumer usa um array e o provider usa uma string, o provider aligns Escopos usando o consumer's list; se o provider usa um array, it apenas processes o provider's list.
- Empty array
[]: results no Escopos being initialized (nodefault, no alignment) — este é uma misconfiguration.
Compartilhe pools são fornecido pelo consumer e initialized pelo provider. Escopos o consumer does não list são filled em as {} (so missing escopo names never crash); Escopos o provider does não list não são initialized. Both sides deve list uma Escopo antes uma shared dep pode really ser reused under it.
Playground
Plugin de build Configuração
Producer
Key points:
shareScope: ['default','scope1']controls que Escopos o provider's remoteEntry initializes em runtime.shared[pkg].shareScopedecides que Escopo uma dependência registers / resolves under. Se@company/design-systemé emscope1, it apenas participates em versão selection e reuse within oscope1pool.
Consumer
Key points:
remotes[remote].shareScopecontrols que Escopos o consumer aligns quando initializing uma provider — they são passed para o provider asshareScopeKeys.- Se o consumer é configured com multiple Escopos but o provider é single-Escopo, o scopeMap é aligned but o provider apenas initializes compartilhamento for its single Escopo (see o combination table above). For multi-pool reuse para "really work", both consumer e provider geralmente precisa agree no mesmo Escopos.
Runtime puro (API de runtime)
Se você não declare providers e dependências compartilhadas por meio do plugin de build (por exemplo, você quiser register them dinamicamente em runtime), você pode use o API de runtime para o mesmo multi-Compartilhe-Escopo effect. Two key APIs:
- Register providers:
registerRemotesoucreateInstance({ remotes }), declaring o Compartilhe Escopos para align viashareScope: string | string[]em each provider configuração. - Register dependências compartilhadas:
registerSharedoucreateInstance({ shared }), deciding que Compartilhe Escopo uma dependência lands em viascope: string | string[]em each entry.
O field name quando registering dependências compartilhadas é scope, não shareScope (diferente do plugin de build's shared[pkg].shareScope).
Fine-grained Control com Hooks de runtime
Multiple Compartilhe Escopos essentially group shared pools by name. Se você need finer control over Escopo selection, alignment, e fallback estratégias, você pode use Hooks de runtime para intervene during o init phase ou shared resolution.
1. Rewrite shareScopeKeys per provider (beforeInitContainer)
O exemplo below forces legacy_remote para always use o legacy Escopo (even se uma diferente shareScope was definir at build time ou runtime registration):
2. Alias / fallback quando uma Escopo é missing (initContainerShareScopeMap / resolveShare)
initContainerShareScopeMap: adjust each Escopo'sshareScopemapping during o provider's compartilhe-pool initialization.resolveShare: override o final selection result by replacingargs.resolver. Returning{ ...args, scope: 'default' }alone é não enough no current runtime implementation.
Exemplo: se uma pacote é não encontrada em scope1, fall back para o default Escopo:
Você pode também alias one Escopo para another em initContainerShareScopeMap (so two Escopos compartilhe o mesmo pool objeto):