Multi-app MicroFrontends in Angular

Github links:
shell-app
find-hotels
account-mgmt

Create 3 Angular apps as usual:

  • ng new hotel-reservation-system --routing --style=scss
  • ng new find-hotels --routing --style=scss
  • ng new account-management --routing --style=scss

Here hotel-reservation-system is the shell app that hosts find-hotels and account-management

Go inside each of the apps and run:

  • ng add @angular-architects/module-federation --project hotel-reservation-system
  • ng add @angular-architects/module-federation --project find-hotels
  • ng add @angular-architects/module-federation --project account-management

Select different default ports if needed. I am selecting

  • hotel-reservation-system: 4200
  • find-hotels: 63402
  • account-management: 63414
In each of the apps, navigate to:
<app>\webpack.config.js

update this:
const { shareAll, withModuleFederationPlugin } = require('@angular-architects/module-federation/webpack');

module.exports = withModuleFederationPlugin({
  name: 'hotel-reservation-system',
  filename: 'remoteEntry.js',
  remotes: {
    './Component': './src/app/app.component.ts',
  },
  shared: {
    ...shareAll({ singleton: true, strictVersion: true, requiredVersion: 'auto' }),
  },
});

<app>\angular.json
"configurations": {
                        "production": {
                            "budgets": [
                                {
                                    "type": "initial",
                                    "maximumWarning": "500kB",
                                    "maximumError": "1MB"
                                },
                                {
                                    "type": "anyComponentStyle",
                                    "maximumWarning": "4kB",
                                    "maximumError": "8kB"
                                }
                            ],
                            "outputPath": "dist/hotel-reservation-system",
                            "builder": "@angular-devkit/build-angular:browser",
                            "moduleFederation": true,
                            "outputHashing": "all",
                            "extraWebpackConfig": "webpack.prod.config.js"
                        },
                        "development": {
                            "optimization": false,
                            "extractLicenses": false,
                            "sourceMap": true
                        }
                    },
                    "defaultConfiguration": "production"
                },

Notice the 3 properties added:
"outputPath": "dist/hotel-reservation-system",
"builder": "@angular-devkit/build-angular:browser",
"moduleFederation": true,


Same way for the other 2 apps:
"outputPath": "dist/find-hotels",
"builder": "@angular-devkit/build-angular:browser",
"moduleFederation": true,

"outputPath": "dist/account-management",
"builder": "@angular-devkit/build-angular:browser",
"moduleFederation": true,


Make sure remoteModule.js is loaded in all the 3 apps, in the browser load:
http://localhost:63414/remoteEntry.js
http://localhost:63402/remoteEntry.js
http://localhost:4200/remoteEntry.js
(or any other port number where your app is running)

We are all set for the apps to talk to each other. 
Run: ng s -o 
make sure all the apps run fine

Now, navigate to the routes of the "hotel-reservation-system" app. 
Lazy load the components of acount management and find hotels

hotel-reservation-system\src\app\app.routes.ts

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

export const routes: Routes = [
    {
        path: 'find-hotels',
        loadComponent: () =>
          loadRemoteModule({
            type: 'module',
            remoteEntry: 'http://localhost:63402/remoteEntry.js',
            exposedModule: './Component'
          }).then(m => m.AppComponent)
    },
    {
        path: 'account-management',
        loadComponent: () =>
          loadRemoteModule({
            type: 'module',
            remoteEntry: 'http://localhost:63414/remoteEntry.js',
            exposedModule: './Component'
          }).then(m => m.AppComponent)
    },
];


And that's it!

Navigate to 
http://localhost:4200/find-hotels
http://localhost:4200/account-management













Comments

Popular posts from this blog

Inside the JavaScript Memory Box: Visualizing Variables, References, and Copies

React & State Management: All Concepts

React: Communication between components