Demonstration Application
The demo project featured here is a compact shell capable of pulling in remotes from both Module Federation and Native Federation. Shared dependencies are coordinated across the two approaches:
Getting Started
Begin by scaffolding a shell with Native Federation, then incorporate the Module Federation Runtime to handle remotes from that ecosystem. The runtime ships inside the @module-federation/enhanced package:
npm i @module-federation/enhanced
For every Native Federation project that installs or employs the Module Federation Runtime, make sure it is excluded from shared dependencies in the federation.config.js:
module.exports = withNativeFederation({
...
skip: [
...
/^@module-federation/,
// Use RegExp to skip ALL entry points!
]
});
Shell Bootstrap
During shell startup, both runtimes need to be initialized side by side:
// main.ts
import { initFederation as initNativeFederation } from '@angular-architects/native-federation';
import { init as initModuleFederation } from '@module-federation/enhanced/runtime';
import { getShared } from './app/shared/federatio-helpers';
(async () => {
// Step 1: Initialize Native Federation
await initNativeFederation('federation.manifest.json');
// Step 2: Get metadata about libs shared via Native Federation
const shared = getShared();
// Step 3: Initialize Module Federation
// Remarks: Consider loading this MF config via the fetch API
initModuleFederation({
name: 'shell',
remotes: [
{
name: 'modfed-mf',
entry: 'http://localhost:4201/remoteEntry.js',
type: 'esm',
},
{
name: 'react',
entry:
'https://witty-wave-0a695f710.azurestaticapps.net/remoteEntry.js',
},
{
name: 'angular2',
entry: 'https://gray-pond-030798810.azurestaticapps.net/remoteEntry.js',
},
{
name: 'angular3',
entry:
'https://gray-river-0b8c23a10.azurestaticapps.net/remoteEntry.js',
}
],
// Step 3a: Delegate shared libs from Native Federation
shared,
})
.initializeSharing();
// Step 4: Delegate to file bootstrapping the SPA
await import('./bootstrap');
})();
The getShared utility (see the accompanying source) extracts metadata about libraries shared through Native Federation. This same metadata is then passed along into the Module Federation setup, creating a bridge between the two worlds.
Fetching the Micro Frontends
When it comes time to load Micro Frontends, pick the right loader: use the helper from @module-federation/enhanced/runtime for Module Federation-based components, and the one from @angular-architects/native-federation (or @softarc/native-federation for non-Angular projects) for Native Federation-based ones:
...
import { loadRemote as loadModuleRemote } from '@module-federation/enhanced/runtime';
import { loadRemoteModule as loadNativeRemote } from '@angular-architects/native-federation';
export const routes: Routes = [
{
path: '',
pathMatch: 'full',
component: HomeComponent,
},
// MF-based Micro Frontend
{
path: 'modfed-mf',
loadComponent: () => loadModuleRemote<any>('modfed-mf/Component').then(m => m.AppComponent)
},
// NF-based Micro Frontend
{
path: 'natfed-mf',
loadComponent: () => loadNativeRemote('natfed-mf', './Component').then(m => m.AppComponent)
},
...
]
To accommodate multiple versions of additional frameworks, the example also includes a Wrapper component that loads Web Components through Federation. That technique is covered in detail elsewhere on this blog.
Looking Ahead
Although the demo illustrates how these two systems can coexist, a production setup would likely benefit from more abstraction. For instance, you could fetch the Module Federation Runtime configuration from a file, mirroring how the federation.manifest.json works for Native Federation.
Another route is to retrieve metadata for both worlds from a service. Then a custom helper could distribute the relevant entries to Module and Native Federation at bootstrap time. That same metadata could also power a loader function capable of deciding, per remote, which federation flavor to invoke.
Deeper Dive: Angular Architecture Workshop (online, interactive, advanced)
Take your skills to the next level and master enterprise-scale, maintainable Angular applications through our Angular Architecture workshop!
All Details (English Workshop) | All Details (German Workshop)
