Configuration
Everything you pass as the second argument to
initFederation lives on this page. Options are grouped
into five concerns — host entry, import-map implementation, logging,
modes, and storage — and every option ships with a sensible default,
so a bare initFederation(manifest) is already a valid
call.
- 1. Host configuration
- 2. Import-map implementation
- 3. Logging
- 4. Modes — strictness & resolution profile
- 5. Storage
1. Host configuration
A host remote entry is a
remoteEntry.json published by the host itself. Whenever
an external appears both in the host entry and in a regular remote,
the host version wins — making this the right escape hatch for locking
a framework or design-system version globally.
type HostOptions = {
hostRemoteEntry?: string | false | {
name?: string;
url: string;
cacheTag?: string;
integrity?: string;
};
manifestIntegrity?: string;
};
| Option | Default | Description |
|---|---|---|
hostRemoteEntry |
false |
Adds a host remoteEntry.json that takes
precedence during shared-version resolution. Can be a URL, the
full object form, or false to disable.
|
hostRemoteEntry.cacheTag |
none |
Opaque string appended as a query parameter — the orchestrator
treats a new cacheTag as a different file and
refetches. Use this to bust caches after a host redeploy.
|
hostRemoteEntry.integrity |
none |
SRI hash (sha256-…, sha384-…,
sha512-…) verified against the response bytes of
the host remoteEntry.json before it is parsed.
See
Security — Subresource Integrity.
|
manifestIntegrity |
none |
SRI hash for the manifest URL passed as the first argument to
initFederation. When set, the orchestrator hashes
the response bytes and rejects with NFError on
mismatch.
|
Example
import { initFederation } from '@softarc/native-federation-orchestrator';
initFederation('http://example.org/manifest.json', {
manifestIntegrity: 'sha384-…',
hostRemoteEntry: {
url: './remoteEntry.json',
cacheTag: 'v1.2.3',
integrity: 'sha384-…',
},
});
Per-remote pinning lives in the manifest itself — entries can be
either the existing string form or a { url, integrity }
object, and the two forms can coexist:
{
"team/mfe1": "https://mfe1.example.org/remoteEntry.json",
"team/mfe2": {
"url": "https://mfe2.example.org/remoteEntry.json",
"integrity": "sha384-…"
}
}
See
Security — Subresource Integrity
for the full trust chain (manifest →
remoteEntry.json → modules) and the supported hash
algorithms.
2. Import-map implementation
The orchestrator commits a standard
import map
to the DOM and uses the browser's own import() to load
modules. For older browsers — or whenever you need
dynamic init — swap
in
es-module-shims.
type ImportMapOptions = {
loadModuleFn?: (url: string) => Promise<unknown>;
setImportMapFn?: (importMap: ImportMap, opts?: { override?: boolean }) => Promise<ImportMap>;
reloadBrowserFn?: () => void;
trustedTypesPolicyName?: string | false;
};
| Option | Default | Description |
|---|---|---|
setImportMapFn |
replaceInDOM('importmap') |
How to commit an import map — by default, replaces any
existing <script type="importmap"> in the
DOM.
|
loadModuleFn |
url => import(url) |
How a module is actually imported. Override when you need the shim loader or custom instrumentation. |
reloadBrowserFn |
() => window.location.reload() |
Called when the SSE dev feature detects a rebuilt remote. Override for custom reload UX. |
trustedTypesPolicyName |
'nfo' |
Name of the
Trusted Types
policy that wraps import-map content and dynamic-import URLs
in the default setImportMapFn and
loadModuleFn. Pass false to opt out
(e.g. when the host owns its own Trusted Types pipeline). No
effect on browsers that do not support Trusted Types — the
wrapper falls back to a transparent pass-through.
|
Two ready-made presets
import 'es-module-shims';
import { initFederation } from '@softarc/native-federation-orchestrator';
import {
useShimImportMap,
useDefaultImportMap,
replaceInDOM,
} from '@softarc/native-federation-orchestrator/options';
initFederation('http://example.org/manifest.json', {
// Option 1 — native import maps (default)
...useDefaultImportMap(),
// Option 2 — es-module-shims
...useShimImportMap({ shimMode: true }),
// Option 3 — custom
loadModuleFn: (url) => customImport(url),
setImportMapFn: replaceInDOM('importmap'),
// Option 4 — rename the Trusted Types policy to match a stricter CSP allowlist
trustedTypesPolicyName: 'my-app-nfo',
});
useShimImportMap is required for dynamic init — native
import maps can be committed to the DOM only once, while
es-module-shims accepts additional maps at runtime.
See Security — Trusted Types for the recommended CSP header and how the orchestrator interacts with a host-defined policy.
3. Logging
Diagnostics for both development and production. Ships with two
built-in loggers and accepts any object that matches the
Logger interface.
type LoggingOptions = {
logger?: Logger;
logLevel?: 'debug' | 'warn' | 'error';
sse?: boolean;
};
interface Logger {
debug(step: number, msg: string, details?: unknown): void;
warn (step: number, msg: string, details?: unknown): void;
error(step: number, msg: string, details?: unknown): void;
}
| Option | Default | Description |
|---|---|---|
logger |
noopLogger |
Where logs go. Use consoleLogger during
development, or provide your own for Sentry / Bugsnag / etc.
|
logLevel |
'error' |
Level threshold. 'warn' emits warn+error;
'debug' emits everything.
|
sse |
false |
Dev feature — listens to server-sent rebuild events from
remotes and triggers reloadBrowserFn.
|
Example
import { initFederation } from '@softarc/native-federation-orchestrator';
import { noopLogger, consoleLogger } from '@softarc/native-federation-orchestrator/options';
initFederation('http://example.org/manifest.json', {
logLevel: 'debug',
logger: consoleLogger, // or noopLogger, or a custom Logger
});
4. Modes — strictness & resolution profile
Mode options are the hyperparameters for the Version Resolver: how strict to be when something unexpected happens, and how aggressively to reuse cached state.
type ModeOptions = {
strict?: boolean | {
strictRemoteEntry?: boolean;
strictExternalCompatibility?: boolean;
strictExternalSameVersionCompatibility?: boolean;
strictExternalVersion?: boolean;
strictImportMap?: boolean;
};
profile?: {
latestSharedExternal?: boolean;
overrideCachedRemotes?: 'always' | 'never' | 'init-only';
overrideCachedRemotesIfURLMatches?: boolean;
};
};
Strictness
All flags default to false, which means "log and
continue". Setting strict: true turns them all on at
once.
| Option | Effect |
|---|---|
strict |
Shortcut — sets every specific strict flag below to
true.
|
strict.strictRemoteEntry |
Throws on malformed remoteEntry.json. When
false, the broken remote is skipped and
initialization continues.
|
strict.strictExternalCompatibility |
Throws when two shared externals have incompatible version
ranges. When false, the incompatible version is
demoted to a scoped external with a warning.
|
strict.strictExternalSameVersionCompatibility
|
Niche edge case — throws when an already-cached shared version
is re-submitted with a different
requiredVersion range. Otherwise, the cached
entry is preserved.
|
strict.strictExternalVersion |
Throws if a shared external's version is missing
or not valid semver. When false, the first entry
matching requiredVersion is picked.
|
strict.strictImportMap |
Throws when the import-map builder encounters corrupt cache state. |
Resolution profile
The profile controls how the resolver picks winners and whether it refreshes cached remotes.
| Option | Default | Description |
|---|---|---|
profile.latestSharedExternal |
false |
When true, always pick the highest version in the
scope. When false (default), pick the version
that minimizes extra scoped downloads.
|
profile.overrideCachedRemotes |
'init-only' |
When to refetch a remote that already lives in cache — see below. |
profile.overrideCachedRemotesIfURLMatches |
false |
By default, a cached remote is only overridden when its URL
changed. Set this to true to force refetch even
when the URL is identical.
|
overrideCachedRemotes values:
-
'never'— don't touch cached remotes, ever. Strongest cache, slowest pickup of new versions. -
'init-only'(default) — allow overrides duringinitFederation, skip during dynamic init. Good compromise. -
'always'— always check and possibly refetch. Use when cache freshness matters more than bandwidth.
Two ready-made profiles
import { initFederation } from '@softarc/native-federation-orchestrator';
import { defaultProfile, cachingProfile } from '@softarc/native-federation-orchestrator/options';
// defaultProfile
// { latestSharedExternal: false, overrideCachedRemotes: 'init-only', overrideCachedRemotesIfURLMatches: false }
// cachingProfile
// { latestSharedExternal: false, overrideCachedRemotes: 'never', overrideCachedRemotesIfURLMatches: false }
initFederation('http://example.org/manifest.json', {
strict: true,
profile: cachingProfile,
});
The caching profile is tempting but comes with a trade-off: newly
deployed remote versions won't be picked up until the cache is
explicitly cleared. Pair it with clearStorage: true on
cache-busting events, or stick with defaultProfile when
remotes change frequently.
5. Storage
The orchestrator keeps its internal caches (remote info, shared
externals, scoped externals) inside a storage entry.
The default is an in-memory map on globalThis, but any
Storage-compatible backend works.
type StorageOptions = {
storage?: StorageEntryCreator;
clearStorage?: boolean;
storageNamespace?: string;
};
| Option | Default | Description |
|---|---|---|
storage |
globalThisStorageEntry |
How the cache is persisted. Built-ins:
globalThisStorageEntry,
sessionStorageEntry,
localStorageEntry. Custom implementations are
supported.
|
clearStorage |
false |
When true, initFederation wipes the
namespace before initializing — handy for one-shot cache busts
after a deploy.
|
storageNamespace |
'__NATIVE_FEDERATION__' |
Namespace prefix for stored keys (e.g.
__NATIVE_FEDERATION__.remotes). Change it to run
multiple orchestrators on the same origin.
|
Example
import { initFederation } from '@softarc/native-federation-orchestrator';
import {
globalThisStorageEntry,
localStorageEntry,
sessionStorageEntry,
} from '@softarc/native-federation-orchestrator/options';
initFederation('http://example.org/manifest.json', {
clearStorage: true,
storageNamespace: '__custom_namespace__',
// Option 1 — in-memory (default)
storage: globalThisStorageEntry,
// Option 2 — persisted for the browser session
storage: sessionStorageEntry,
// Option 3 — persisted across browser restarts
storage: localStorageEntry,
});
Most server-rendered hosts want sessionStorageEntry: it
survives navigation-triggered full reloads (the whole point of
caching here) but is automatically cleared when the tab closes, so a
stale resolution can never live longer than the user's session.
Putting it together
import { initFederation } from '@softarc/native-federation-orchestrator';
import {
consoleLogger,
sessionStorageEntry,
useShimImportMap,
cachingProfile,
} from '@softarc/native-federation-orchestrator/options';
const { loadRemoteModule } = await initFederation(manifest, {
// Host
hostRemoteEntry: { url: './host-remoteEntry.json', cacheTag: '2025-04-22' },
// Import map
...useShimImportMap({ shimMode: true }),
// Logging
logLevel: 'warn',
logger: consoleLogger,
// Modes
strict: { strictRemoteEntry: true, strictExternalCompatibility: true },
profile: cachingProfile,
// Storage
storage: sessionStorageEntry,
storageNamespace: '__NATIVE_FEDERATION__',
clearStorage: false,
});
See also
- The orchestrator docs — Which shows a bit more in-depth how the orchestrator can be configured.
-
Security & Subresource Integrity —
CSP setup for the built-in Trusted Types policy and the SRI trust
chain (manifest →
remoteEntry.json→ modules). - Version Resolver — how the profile and strictness flags actually shape resolution output.
- Architecture — caches — what lives in the storage namespace.
- Getting Started — worked examples for the quickstart, registry and custom setups.