initFederation
initFederation is the one call a host needs to make
before any remote can be loaded. It fetches the host's own
remoteEntry.json, fetches every configured remote's
remoteEntry.json in parallel, merges everything into a
single import map and injects it into the DOM.
Signature
function initFederation(
remotesOrManifestUrl?: Record<string, string> | string,
options?: InitFederationOptions,
): Promise<ImportMap>;
interface InitFederationOptions {
cacheTag?: string;
}
The first argument is either an inline
{ remoteName: remoteEntryUrl } map or a URL string that
resolves to such a map (a manifest). If you pass nothing, the runtime
still loads the host's own remoteEntry.json — useful when
a project only needs its own shared deps registered (this is the shape
a remote uses).
The returned promise resolves to the final merged
ImportMap that was written
into the DOM.
The initialization flow
On every call the runtime does exactly this, in order:
-
If the first argument is a string, fetch it and
JSON.parseit into a remotes record. -
Fetch the host's
./remoteEntry.json— the host's build output must be served at the same origin as the host page itself. -
Build the host's import map: every
shared[]entry becomes a root import keyed by package name. -
Kick off one
fetchAndRegisterRemotepromise per remote, in parallel. Each one:- fetches the remote's
remoteEntry.json; - registers the remote in the global registry;
-
adds exposed modules as root imports
(
<remoteName>/<exposedKey>); - adds shared deps and chunks under a scope keyed by the remote's base URL.
- fetches the remote's
- Merge all successful maps into one
ImportMap. -
Inject that map as
<script type="importmap-shim">viadocument.head.appendChild.
The injection goes through a TrustedTypes policy called
native-federation when the browser has Trusted Types
enabled, so the runtime plays nicely with strict CSPs. See
The Import Map → Trusted Types.
Inline remotes
If you know which remotes you need at build time, pass them directly:
import { initFederation } from '@softarc/native-federation-runtime';
await initFederation({
mfe1: 'http://localhost:3001/remoteEntry.json',
mfe2: 'https://cdn.example.com/orders/remoteEntry.json',
});
The key is the remote name you will pass to
loadRemoteModule. It does not have to match the
name field inside the remote's
remoteEntry.json — the key you supply here wins. If you
leave it out (via fetchAndRegisterRemote) the name falls
back to remoteEntry.name.
Manifest URL
Pass a string to defer the remotes map to runtime:
await initFederation('/assets/federation.manifest.json');
The manifest is just JSON mapping remote names to
remoteEntry.json URLs:
{
"mfe1": "http://localhost:3001/remoteEntry.json",
"mfe2": "https://cdn.example.com/orders/remoteEntry.json"
}
Ship a different manifest per environment to re-point remotes without
rebuilding the host. Relative URLs are resolved by the browser against
the page, so ./remoteEntry.json and absolute URLs both
work.
Cache busting with cacheTag
If you set options.cacheTag, the runtime appends
?t=<cacheTag> (or &t=... when the
URL already has a query string) to every network request it
makes — the manifest URL, the host remoteEntry.json, and
every remote remoteEntry.json:
await initFederation('/assets/federation.manifest.json', {
cacheTag: BUILD_HASH,
});
Use a deployment-stable value — a build hash, a git SHA, a CI run ID. It only affects metadata fetches; the actual module bundles are loaded through the import map and have their own hashed filenames.
cacheTag is the only option the classic
runtime exposes. There is no persistent cache, no logger injection
and no storage layer — those belong to the
Orchestrator.
Remote load errors
If a single remote fails to load (network error, 404, invalid JSON),
initFederation does not fail the whole
operation. It logs the error to console.error and
continues with the remotes that did load. The rationale is that one
flaky remote should not bring the host down.
If you need strict behaviour, call
fetchAndRegisterRemotes directly with
throwIfRemoteNotFound: true:
import {
initFederation,
fetchAndRegisterRemotes,
} from '@softarc/native-federation-runtime';
await fetchAndRegisterRemotes(
{ mfe1: 'http://localhost:3001/remoteEntry.json' },
{ throwIfRemoteNotFound: true },
);
Note that this only changes behaviour for remote load errors.
If the host's own remoteEntry.json cannot be
fetched or parsed, initFederation rejects — no fallback.
Hot reload watching
If a remote's remoteEntry.json contains a
buildNotificationsEndpoint field,
fetchAndRegisterRemote opens an
EventSource on it. When the dev server emits
{ type: 'federation-rebuild-complete' }, the runtime
calls window.location.reload(). This is how Angular's
ng serve integration triggers a reload after a federation
rebuild.
In production builds the endpoint is not written to
remoteEntry.json, so no SSE connection is opened. You do
not need to configure anything on the runtime side — it is purely a
function of the build output.
Calling it from a remote
A remote calls initFederation too — usually with an empty
remotes map:
// remote src/main.ts
initFederation({})
.catch(err => console.error(err))
.then(() => import('./bootstrap'));
This loads the remote's own remoteEntry.json and
registers its shared dependencies at the root of the import map, so
the remote's code resolves @angular/core,
rxjs and friends to the bundled versions when running the
remote directly. If the remote is only ever loaded through a host,
this call can be omitted — the host's initFederation will
register the remote's shared deps under a scope instead.
Related
-
loadRemoteModule— the companion call used from routes/components. -
The Import Map — what
initFederationwrites todocument.head. -
API Reference —
fetchAndRegisterRemote,processHostInfoand the lower-level building blocks.