Tutorial: Module Federation Tools
September 11, 2022 ยท View on GitHub
This tutorial is an extension for the @angular-architects/module-federation tutorial here and shows, how to use the add-on lib @angular-architects/module-federation-tools to load web components exposed via module federation.
Getting Started
Option A: Start with the Upstream Tutorial
Please find the upstream tutorial this tutorial extends here.
Option B: Checkout the Starter Kit
If you don't want to do the upstream tutorial first, you can use this example (see main branch) as the starting point.
Part 1: Routing to Web Components
-
Install
@angular-architects/module-federation-tools:npm i @angular-architects/module-federation-tools -
Restart your VS Code (or your TS Server within VS Code at least)
-
Open your shell's
app.routes.tsand add the following routes:[...] // Add this import: import { WebComponentWrapper, WebComponentWrapperOptions, startsWith } from '@angular-architects/module-federation-tools'; [...] export const APP_ROUTES: Routes = [ [...] // Add these routes: { path: 'react', component: WebComponentWrapper, data: { type: 'script', remoteEntry: 'https://witty-wave-0a695f710.azurestaticapps.net/remoteEntry.js', remoteName: 'react', exposedModule: './web-components', elementName: 'react-element' } as WebComponentWrapperOptions }, { path: 'angular1', component: WebComponentWrapper, data: { type: 'script', remoteEntry: 'https://nice-grass-018f7d910.azurestaticapps.net/remoteEntry.js', remoteName: 'angular1', exposedModule: './web-components', elementName: 'angular1-element' } as WebComponentWrapperOptions }, { path: 'angular2', component: WebComponentWrapper, data: { type: 'script', remoteEntry: 'https://gray-pond-030798810.azurestaticapps.net//remoteEntry.js', remoteName: 'angular2', exposedModule: './web-components', elementName: 'angular2-element' } as WebComponentWrapperOptions }, { matcher: startsWith('angular3'), component: WebComponentWrapper, data: { type: 'script', remoteEntry: 'https://gray-river-0b8c23a10.azurestaticapps.net/remoteEntry.js', remoteName: 'angular3', exposedModule: './web-components', elementName: 'angular3-element' } as WebComponentWrapperOptions }, { path: 'vue', component: WebComponentWrapper, data: { type: 'script', remoteEntry: 'https://mango-field-0d0778c10.azurestaticapps.net/remoteEntry.js', remoteName: 'vue', exposedModule: './web-components', elementName: 'vue-element' } as WebComponentWrapperOptions }, { path: 'angularjs', component: WebComponentWrapper, data: { type: 'script', remoteEntry: 'https://calm-mud-0a3ee4a10.azurestaticapps.net/remoteEntry.js', remoteName: 'angularjs', exposedModule: './web-components', elementName: 'angularjs-element' } as WebComponentWrapperOptions }, { matcher: startsWith('angular3'), component: WebComponentWrapper, data: { type: 'script', remoteEntry: 'https://gray-river-0b8c23a10.azurestaticapps.net/remoteEntry.js', remoteName: 'angular3', exposedModule: './web-components', elementName: 'angular3-element' } as WebComponentWrapperOptions }, // THIS needs to be the last route!!! { path: '**', component: NotFoundComponent } ];Remarks: The URL matcher
startsWithmakes the shell to ignore the remaining part of the URL. This is necessary when the loaded micro frontend uses a router too.Remarks: Please note that we are using
type: 'script'here. This is needed for classic webpack setups as normally used in the Vue and React world as well as for Angular before version 13. Beginning with version 13, the CLI emits EcmaScript module instead of "plain old" JavaScript files. Hence, when loading a remote compiled with Angular 13 or higher, you need to settypetomodule. In our case, however, the remotes we find at the shown URLs in the cloud are Angular 12-based, hence we needtype: 'script'. -
Open your shell's
app.component.htmland add the following links:<!-- Add these links --> <li><a routerLink="/react">React</a></li> <li><a routerLink="/angular1">Angular 1</a></li> <li><a routerLink="/angular2">Angular 2</a></li> <li><a routerLink="/angular3/a">Angular 3</a></li> <li><a routerLink="/vue">Vue</a></li> <li><a routerLink="/angularjs">AngularJS</a></li> -
Open your shell's
bootstrap.tsand use thebootstraphelper function found in@angular-architects/module-federation-toolsfor bootstrapping:import { AppModule } from './app/app.module'; import { environment } from './environments/environment'; import { bootstrap } from '@angular-architects/module-federation-tools'; bootstrap(AppModule, { production: environment.production, appType: 'shell', });Remarks: This special bootstrap function takes care of some workarounds necessary to run several versions of Angular side by side.
-
Start your
shelland themfe1project (e. g. by callingnpm run run:all) and try it out.
Part 2: Inspect the Web-Component-based Micro Frontends
In this part of the lab, we will investigate the loaded micro frontend that has been called "MF Angular #3" before. We want to draw your attention to the following details:
-
The application is bootstrapped with the bootstrap function already used above. Please note that here,
appTypeis set tomicrofrontend. -
The
AppModuleis wrapping some components as web components using Angular Elements in it's ngDoBootstrap method. -
The webpack config exposes the whole
bootstrap.tsfile. Hence, everyone importing it can use the provided web components. -
The webpack config shares libraries like
@angular/core.
More Details on Module Federation **
If you would like to know more about Module Federation with Angular take a look at this article series about Module Federation.