A Guide to Module Federation and Micro-Frontend Applications in Angular — Part 2

Hürkan UĞUR
4 min readMay 26, 2024

--

1) Create the Host Application

ng new host

2) Create the Micro-Frontend Applications

ng new teams
ng new calendar

3) Upgrade Angular Versions of Each Application

ng update @angular/cli @angular/core --allow-dirty

4) Install PrimeNG for All Applications For Styling (Optional)

npm i primeng@latest
npm i primeicons

src/style.css:

@import "primeng/resources/themes/bootstrap4-light-blue/theme.css";
@import "primeng/resources/primeng.css";
@import "primeicons/primeicons.css";

* {
padding: 0;
margin: 0;
box-sizing: border-box;
}
body {
font-family: var(--font-family);
}

5) Migrate the Existing Angular Projects to Standalone

Run the command below and select “Convert all components, directives and pipes to standalone”:

ng g @angular/core:standalone

Run the command below and select “Remove unnecessary NgModule classes”:

ng g @angular/core:standalone

Run the command below and select “Bootstrap the project using standalone APIs”:

ng g @angular/core:standalone

6) Bootstrapping the Apps with Standalone Components

Delete the AppComponent and create your own Standalone Components for all projects:

ng g c host --standalone
ng g c teams --standalone
ng g c calendar --standalone

Create route files for all projects (The route list will be provided during the Module Federation setup):

host/src/app/routes/host.routes.ts:

export const HOST_ROUTES: Routes = [];

calendar/src/app/routes/calendar.routes.ts:

export const CALENDAR_ROUTES: Routes = [];

teams/src/app/routes/teams.routes.ts:

export const TEAMS_ROUTES: Routes = [];

Update the index.html to specify the application’s entry point for all projects:

host/src/index.html:

<body>
<app-host></app-host>
</body>

calendar/src/index.html:

<body>
<app-calendar></app-calendar>
</body>

teams/src/index.html:

<body>
<app-teams></app-teams>
</body>

Update the main.ts to migrate to BootstrapApplication:

host/src/main.ts:

import { importProvidersFrom } from "@angular/core";
import { bootstrapApplication, BrowserModule } from "@angular/platform-browser";
import { provideRouter, RouterModule, withComponentInputBinding } from "@angular/router";

bootstrapApplication(HostComponent, {
providers: [
importProvidersFrom(
BrowserModule,
RouterModule,
),
provideRouter(
HOST_ROUTES,
withComponentInputBinding(), // For Input Binding (Requires Angular Version 16+)
)
],
});

calendar/src/main.ts:

import { importProvidersFrom } from "@angular/core";
import { bootstrapApplication, BrowserModule } from "@angular/platform-browser";
import { provideRouter, RouterModule, withComponentInputBinding } from "@angular/router";

bootstrapApplication(CalendarComponent, {
providers: [
importProvidersFrom(
BrowserModule,
RouterModule,
),
provideRouter(
CALENDAR_ROUTES,
withComponentInputBinding(), // For Input Binding (Requires Angular Version 16+)
)
],
});

teams/src/main.ts:

import { importProvidersFrom } from "@angular/core";
import { bootstrapApplication, BrowserModule } from "@angular/platform-browser";
import { provideRouter, RouterModule, withComponentInputBinding } from "@angular/router";

bootstrapApplication(TeamsComponent, {
providers: [
importProvidersFrom(
BrowserModule,
RouterModule,
),
provideRouter(
TEAMS_ROUTES,
withComponentInputBinding(), // For Input Binding (Requires Angular Version 16+)
)
],
});

7) Module Federation Setup

Install dependencies for Module Federation:

npm i @angular-architects/module-federation

Migrate micro-frontend apps to Module Federation:

ng add @angular-architects/module-federation --project calendar --port 4201 --type remote
ng add @angular-architects/module-federation --project teams --port 4202 --type remote

Migrate the host app to Module Federation:

ng add @angular-architects/module-federation --project host --port 4200 --type dynamic-host

As a result:

  • Main.ts files will have been moved to the bootstrap.ts. Check all projects and fix if AppComponent is used instead of Standalone Components.
  • Index.html files may have changed. Check all projects and fix if AppComponent is used instead of Standalone Components.
  • In the host project, you can manage micro-frontends and their ports through the host/src/assets/mf.manifest.json file.

Declare the micro-frontend endpoints in the Host App:

host/src/assets/mf.manifest.json:

{
"calendar": "http://localhost:4201/remoteEntry.js",
"teams": "http://localhost:4202/remoteEntry.js"
}

Expose route files of the micro-frontends via their webpack.config.js:

calendar/webpack.config.js:

exposes: {
'./routes': './src/app/routes/calendar.routes.ts'
}

teams/webpack.config.js:

exposes: {
'./routes': './src/app/routes/teams.routes.ts'
}

Fill in the contents of the Route files in each project:

calendar/src/app/routes/calendar.routes.ts:

export const CALENDAR_ROUTES: Routes = [
{ path: '', redirectTo: 'menu', pathMatch: "full" },
{
path: 'menu',
loadComponent: () => import('../calendar.component')
.then(c => c.CalendarComponent)
},
{ path: '**', redirectTo: 'menu' },
];

teams/src/app/routes/teams.routes.ts:

export const TEAMS_ROUTES: Routes = [
{ path: '', redirectTo: 'menu', pathMatch: "full" },
{
path: 'menu',
loadComponent: () => import('../teams.component')
.then(c => c.TeamsComponent)
},
{ path: '**', redirectTo: 'menu' },
];

host/src/app/routes/host.routes.ts:

import { loadRemoteModule } from '@angular-architects/module-federation';

export const HOST_ROUTES: Routes = [
{ path: '', redirectTo: "calendar", pathMatch: "full" },
{
path: 'calendar',
loadChildren: () => loadRemoteModule({
type: 'manifest',
remoteName: 'calendar', // The name that is written in assets/mf.manifest.json
exposedModule: './routes'
}).then(r => r.CALENDAR_ROUTES),
},
{
path: 'teams',
loadChildren: () => loadRemoteModule({
type: 'manifest',
remoteName: 'teams', // The name that is written in assets/mf.manifest.json
exposedModule: './routes'
}).then(r => r.TEAMS_ROUTES),
},
{ path: "**", redirectTo: 'calendar', pathMatch: "full" }
];

8) Run the Apps

Run the Micro-Frontend Applications:

ng serve

Run the Host Application:

ng serve

9) Application Screenshots

The image of the Teams micro-frontend application within the host app and on its own.
The image of the Chat micro-frontend application within the host app and on its own.
The image of the Mail micro-frontend application within the host app and on its own.

--

--

Hürkan UĞUR

Software Engineer @TÜBİTAK (Scientific and Technological Research Council of Türkiye)