Ir al contenido

Native Federation (esbuild & Vite)

Esta página aún no está disponible en tu idioma.

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).


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)”
  1. Tooling-Agnostic Engine: Native Federation acts as a lightweight compilation wrapper. It delegates bundling to the underlying builder (like Angular’s ApplicationBuilder powered by esbuild) and then compiles a metadata descriptor file: remoteEntry.json.
  2. Standardized Communication: It communicates with bundlers via exchangeable adapters, guaranteeing future-proof integration regardless of subsequent internal Angular CLI compiler innovations.
  3. 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.
  4. Dynamic Manifests: Native Federation natively supports dynamic hosts. Instead of hardcoding remote URLs at build-time, you can pass a federation.manifest.json file during bootstrap, allowing systems to swap upstream remote addresses dynamically in production or use an API registry service.
  5. 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.

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:

Terminal window
ng add @angular-architects/native-federation --type host

For a Remote Application:

Terminal window
ng add @angular-architects/native-federation --type remote

This schematic command:

  1. Adjusts your angular.json build mapping to utilize Native Federation wrappers.
  2. Generates a simplified, standalone federation.config.js in the application’s root directory.
  3. Sets up an asynchronous bootstrap system (main.ts loading bootstrap.ts dynamically).

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"
}

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'
}
];

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.