Native Federation (esbuild & Vite)
Microfrontends with Angular & Native Federation
Section titled “Microfrontends with Angular & Native Federation”In modern Angular applications (from version 17 onwards, including 18 and 19), classical Webpack-based Module Federation exhibits a major architectural drawback: it forces the build pipeline to use the legacy Webpack compiler instead of the extremely fast, native esbuild-based Application Builder (@angular-devkit/build-angular:application).
To get the best of both worlds—modular microfrontend scalability and near-instant esbuild compilation speeds—the Angular ecosystem leverages Native Federation (developed by the @angular-architects team led by Manfred Steyer).
1. What is Native Federation?
Section titled “1. What is Native Federation?”Native Federation is a build-tool agnostic implementation of Module Federation. Instead of relying on Webpack’s internal runtime loader, it executes directly on top of native browser Web Standards:
- Browsers-Native ES Modules (ESM) to resolve, download, and load modules dynamically at runtime.
- Import Maps to negotiate and coordinate shared package versions between the Host/Shell and Remote MFEs in the browser.
Because it operates at the ES Module level rather than hooking into custom Webpack bundler internals, it works out-of-the-box with any modern compiler (esbuild, Vite, Rollup, Webpack) and fully supports development-oriented setups like Vite-powered dev servers.
Core Architectural Concepts (Manfred Steyer’s Design)
Section titled “Core Architectural Concepts (Manfred Steyer’s Design)”- Tooling-Agnostic Engine: Native Federation acts as a lightweight compilation wrapper. It delegates bundling to the underlying builder (like Angular’s
ApplicationBuilderpowered byesbuild) and then compiles a metadata descriptor file:remoteEntry.json. - Standardized Communication: It communicates with bundlers via exchangeable adapters, guaranteeing future-proof integration regardless of subsequent internal Angular CLI compiler innovations.
- Severe Compile-Time & Runtime Independence: By switching from compile-time resolution to runtime ES Modules, teams get absolute deployment autonomy. However, this relies on a formal versioning negotiation in the browser.
- Dynamic Manifests: Native Federation natively supports dynamic hosts. Instead of hardcoding remote URLs at build-time, you can pass a
federation.manifest.jsonfile during bootstrap, allowing systems to swap upstream remote addresses dynamically in production or use an API registry service. - Modern Feature Compatibility: Unlike Webpack Module Federation, Native Federation supports advanced CLI operations natively, including Server-Side Rendering (SSR) and Hydration, which are essential for performance-critical architectures.
2. Step-by-Step Implementation Guide
Section titled “2. Step-by-Step Implementation Guide”Follow this guide to initialize, configure, and orchestrate a Host Shell and Remote microfrontends using Native Federation.
Step 1: Add Native Federation dependency to your workspace
Section titled “Step 1: Add Native Federation dependency to your workspace”Instead of using the classic module federation bundle, add Native Federation using the official schematics.
For the Host/Shell Application:
ng add @angular-architects/native-federation --type hostFor a Remote Application:
ng add @angular-architects/native-federation --type remoteThis schematic command:
- Adjusts your
angular.jsonbuild mapping to utilize Native Federation wrappers. - Generates a simplified, standalone
federation.config.jsin the application’s root directory. - Sets up an asynchronous bootstrap system (
main.tsloadingbootstrap.tsdynamically).
Step 2: Configure federation.config.js
Section titled “Step 2: Configure federation.config.js”Unlike webpack.config.js which is highly verbose, Native Federation relies on a clean, declarative configuration file. Additionally, you can utilize the skip array to prune unneeded RxJS paths or libraries from runtime sharing to optimize performance and prevent bundle bloating:
const { withNativeFederation, shareAll } = require('@angular-architects/native-federation/config');
module.exports = withNativeFederation({ name: 'coreFeatureRemote',
exposes: { './Component': './src/app/feature-entry/feature-entry.component.ts', },
shared: { ...shareAll({ singleton: true, strictVersion: true, requiredVersion: 'auto' }), },
skip: [ 'rxjs/ajax', 'rxjs/fetch', 'rxjs/testing', 'rxjs/webSocket', ]});Step 3: Initialize Dynamic Import Maps in main.ts
Section titled “Step 3: Initialize Dynamic Import Maps in main.ts”During bootstrap, the Shell needs to resolve the locations of all remotes’ remoteEntry.json metadata files to construct the local browser import maps. This can be hardcoded or loaded dynamically via a standalone JSON manifest file (e.g., federation.manifest.json), which is ideal for multi-environment deployments (such as dev, sandbox, production):
import { initFederation } from '@angular-architects/native-federation';
initFederation({ 'coreFeatureRemote': 'http://localhost:4201/remoteEntry.json'})*/
initFederation('federation.manifest.json') .catch((err) => console.error('Error loading dynamic configuration manifest:', err)) .then(() => import('./bootstrap')) .catch((err) => console.error('Bootstrap integration error:', err));The dynamic federation.manifest.json placed inside your host’s dynamic output folder (usually /public or /assets) simply references the remote directories:
{ "coreFeatureRemote": "http://localhost:4201/remoteEntry.json"}Step 4: Router Dynamic Loading
Section titled “Step 4: Router Dynamic Loading”To load exposed remote components or modules dynamically inside your Angular Host Router, resolve dependencies via the loadRemoteModule utility:
import { Routes } from '@angular/router';import { loadRemoteModule } from '@angular-architects/native-federation';
export const routes: Routes = [ { path: 'core-feature', loadComponent: () => loadRemoteModule('coreFeatureRemote', './Component').then((m) => m.FeatureComponent), }, { path: '**', redirectTo: 'core-feature', pathMatch: 'full' }];3. Comparison and Orchestration Choices
Section titled “3. Comparison and Orchestration Choices”To understand the core differences between Native Federation, Webpack Module Federation, and framework-agnostic lifecycle managers like Single-SPA, check out our comprehensive src/content/docs/angular/architecture/federation-comparison.mdx handbook.
In addition, before migrating to a distributed system, review the architectural trade-offs, potential drawbacks, and common runtime troubleshooting approaches (such as the eager consumption error and Zone.js conflicts) in our src/content/docs/angular/architecture/federation-common-issues.mdx guide.