Getting Started
Install the adapter, run ng add on every project that
should participate in the federation, and you have a working host +
remote pair within minutes. This page walks the happy path; the
Tutorial goes through a complete
example.
Source on GitHub: native-federation/playground.
1. Install
npm i @angular-architects/native-federation -D
Which package? From Angular 22 the
adapter is back under its original name,
@angular-architects/native-federation (22.x). If you are
still on Angular 20 or 21, install
@angular-architects/native-federation-v4 instead — it is
the exact same adapter, only the package name differs, so substitute
-v4 in every command and import on these pages. Pin the
adapter to the same major as your Angular CLI.
| Your Angular | Install |
|---|---|
| 22+ | @angular-architects/native-federation |
| 20 – 21 | @angular-architects/native-federation-v4 |
The package brings
@softarc/native-federation (^4.0.0) and
@softarc/native-federation-orchestrator (^4.0.0)
as dependencies. The ng add step below adds
es-module-shims,
@angular-devkit/build-angular and
@softarc/native-federation-orchestrator (as a
devDependency) on top — nothing else to install up front.
2. Scaffold a Remote (Micro Frontend)
ng g @angular-architects/native-federation:init --project mfe1 --port 4201 --type remote
This runs the init schematic against mfe1.
See Schematics → init for the full
list of changes; in summary it:
- Adds
es-module-shimsto the polyfills. -
Generates
projects/mfe1/federation.config.mjswith one entry exposed (./Component→ the project'sapp.component.ts). -
Generates
projects/mfe1/tsconfig.federation.json. -
Renames the existing
build/servetargets inangular.jsontoesbuild/serve-originaland pointsbuild/serveat@angular-architects/native-federation:build. -
Splits
main.tsin two: an orchestrator-based federation bootstrap, and the original Angular bootstrap moved tobootstrap.ts.
3. Scaffold a Host (Shell)
ng g @angular-architects/native-federation:init --project shell --port 4200 --type dynamic-host
The same schematic runs in dynamic-host mode for the
shell. In addition to the changes above, it creates a
federation.manifest.json in the project's
public/ (or src/assets/) folder listing the
remotes it knows about:
{
"mfe1": "http://localhost:4201/remoteEntry.json"
}
Pick the type that fits the role of the project:
--type |
What you get | When to use it |
|---|---|---|
remote |
main.ts calls
initFederation({ '<name>': './remoteEntry.json'
})
— exposes its own remoteEntry.json.
|
Every Micro Frontend. |
host |
Remote map is inlined in main.ts. |
Single-environment shells where remote URLs never change. |
dynamic-host |
main.ts reads from
federation.manifest.json.
|
The default for shells — swap the manifest per environment without rebuilding. |
4. Wire a Lazy Route in the Host
Loading a remote module is plain Angular lazy-loading with
loadRemoteModule in place of a dynamic
import(). On v4 the schematic wires the orchestrator
directly — the generated main.ts initialises federation,
then dynamically imports your Angular bootstrap:
// projects/shell/src/main.ts (generated)
import { initFederation } from '@softarc/native-federation-orchestrator';
import {
useShimImportMap,
consoleLogger,
globalThisStorageEntry,
} from '@softarc/native-federation-orchestrator/options';
initFederation('/assets/federation.manifest.json', {
...useShimImportMap({ shimMode: true }),
logger: consoleLogger,
storage: globalThisStorageEntry,
hostRemoteEntry: './remoteEntry.json',
logLevel: 'debug',
})
.catch(err => console.error(err))
.then(_ => import('./bootstrap'))
.catch(err => console.error(err));
With that generated bootstrap, routes use the
loadRemoteModule re-exported from the adapter package:
// projects/shell/src/app/app.routes.ts
import { Routes } from '@angular/router';
import { loadRemoteModule } from '@angular-architects/native-federation';
export const routes: Routes = [
{
path: 'flights',
loadComponent: () =>
loadRemoteModule('mfe1', './Component').then(m => m.AppComponent),
},
];
That top-level loadRemoteModule is convenient but
deprecated. For the recommended pattern — taking
loadRemoteModule off the resolved
initFederation promise and threading it through
Angular's DI — see Runtime.
5. Run It
ng serve mfe1 -o # in one terminal
ng serve shell -o # in another
The shell's dev server proxies
http://localhost:4201/remoteEntry.json at request time
and lazy-loads the remote when the route is hit. The Angular adapter's
dev server also serves the federation artifacts (shared bundles,
exposed modules) directly from
dist/<project>/browser, so you don't need a
separate static server.
What Got Generated
After running ng add against a project, expect the
following layout:
projects/mfe1/
├── federation.config.mjs ← shared/exposes config (see Angular Config)
├── tsconfig.federation.json ← extends tsconfig.json, used only by the federation builder
└── src/
├── main.ts ← initFederation(...) bootstrap (orchestrator by default)
└── bootstrap.ts ← the *original* Angular bootstrap (bootstrapApplication etc.)
And in the workspace root:
angular.json ← build → @angular-architects/native-federation:build
← serve → @angular-architects/native-federation:build
← esbuild → @angular/build:application (the original build)
← serve-original → @angular/build:dev-server (the original serve)
package.json ← + es-module-shims, + @softarc/native-federation-orchestrator (devDep)
Production Builds
ng build mfe1
ng build shell --configuration production
Each project's output (dist/<project>/browser/)
contains a remoteEntry.json alongside the Angular bundle.
Deploy the whole folder as a static site; the host's manifest only
needs to point at the matching remoteEntry.json URL.
The shape of remoteEntry.json, the import map and the
artifact cache are all produced by the core. See
Build Artifacts for the full
layout.
Next Steps
-
Builder — every option in the
angular.jsontargets the schematic created. -
Angular Config — what
withNativeFederationchanges for Angular projects. -
Runtime —
initFederation,loadRemoteModuleand the orchestrator. - Tutorial — full host + remote walkthrough on a real example repo.