Forcing Module Federation: A Step-by-Step Guide to Bootstrapping Routing, NgRx, and More in an MFE Module from a Shell Project
Image by Honi - hkhazo.biz.id

Forcing Module Federation: A Step-by-Step Guide to Bootstrapping Routing, NgRx, and More in an MFE Module from a Shell Project

Posted on

Are you struggling to integrate your Micro Frontend (MFE) module with a shell project using Module Federation? Look no further! In this comprehensive guide, we’ll show you how to bootstrap the routing, NgRx, and other essential components of your MFE module from the shell project forcibly, using Module Federation.

Why Module Federation?

Module Federation is a revolutionary approach to building scalable, maintainable, and highly performant Micro Frontend applications. By allowing multiple modules to communicate and share resources, Module Federation enables developers to create complex applications with ease. However, as with any innovative technology, it can be challenging to set up and configure, especially when it comes to integrating with existing projects.

Prerequisites

Before we dive into the tutorial, make sure you have the following installed on your machine:

  • Node.js (version 14 or higher)
  • yarn or npm (we’ll use yarn in this example)
  • Angular CLI (version 12 or higher)
  • Module Federation (version 1.2 or higher)
  • NgRx (version 12 or higher)

Step 1: Create a New Shell Project

Let’s create a new shell project using the Angular CLI:

yarn new my-shell-project --routing

This will create a new Angular project with routing enabled.

Step 2: Create a New MFE Module

Next, create a new MFE module using the Angular CLI:

yarn new my-mfe-module --routing

This will create a new Angular project with routing enabled, which we’ll use as our MFE module.

Step 3: Configure Module Federation

In the shell project, create a new file called `module-federation.config.js` with the following content:

module.exports = {
  name: 'shell',
  exposes: {
    './ShellAppModule': './src/app/shell-app.module.ts',
  },
};

This configuration tells Module Federation that our shell project exposes the `ShellAppModule` as a module that can be imported by other projects.

Step 4: Configure the MFE Module

In the MFE module, create a new file called `module-federation.config.js` with the following content:

module.exports = {
  name: 'mfe',
  exposes: {
    './MfeAppModule': './src/app/mfe-app.module.ts',
  },
  remotes: {
    shell: 'shell@http://localhost:4200/remoteEntry.js',
  },
};

This configuration tells Module Federation that our MFE module exposes the `MfeAppModule` and imports the `ShellAppModule` from the shell project.

Step 5: Bootstrap the MFE Module

In the MFE module, create a new file called `bootstrap.ts` with the following content:

import { enableProdMode } from '@angular/core';
import { environment } from './environments/environment';
import { MfeAppModule } from './app/mfe-app.module';
import { provideHttpClientTesting } from '@angular/common/http/testing';

if (environment.production) {
  enableProdMode();
}

document.addEventListener('DOMContentLoaded', () => {
  import('zone.js/dist/zone').then((zone) => {
    zone.Zone.current.inject();
  });
});

provideHttpClientTesting();

platformBrowserDynamic()
  .bootstrapModule(MfeAppModule)
  .catch((err) => console.error(err));

This file bootstraps the MFE module using the `platformBrowserDynamic` API from Angular.

Step 6: Integrate NgRx

In the MFE module, create a new file called `ngrx.module.ts` with the following content:

import { NgModule } from '@angular/core';
import { StoreModule } from '@ngrx/store';
import { EffectsModule } from '@ngrx/effects';
import { reducers, metaReducers } from './reducers/index';
import { effects } from './effects/index';

@NgModule({
  imports: [
    StoreModule.forRoot(reducers, { metaReducers }),
    EffectsModule.forRoot(effects),
  ],
})
export class NgrxModule {}

This file configures NgRx for our MFE module.

Step 7: Integrate Routing

In the MFE module, create a new file called `app-routing.module.ts` with the following content:

import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { MfeAppComponent } from './mfe-app.component';

const routes: Routes = [
  {
    path: '',
    component: MfeAppComponent,
  },
];

@NgModule({
  imports: [RouterModule.forRoot(routes)],
  exports: [RouterModule],
})
export class AppRoutingModule {}

This file configures the routing for our MFE module.

Step 8: Forcibly Load the MFE Module

In the shell project, create a new file called `force-load-mfe.module.ts` with the following content:

import { NgModule } from '@angular/core';
import { LoadRemoteModule } from '@angular-architects/module-federation/runtime';
import { MfeAppModule } from '../mfe/src/app/mfe-app.module';

@NgModule({
  imports: [
    LoadRemoteModule.forRoot({
      remoteName: 'mfe',
      exposedModule: './MfeAppModule',
      remoteUrl: 'http://localhost:4201/remoteEntry.js',
    }),
  ],
})
export class ForceLoadMfeModule {}

This file forcibly loads the MFE module from the shell project using the `LoadRemoteModule` API from Module Federation.

Step 9: Bootstrap the Shell Project

In the shell project, update the `app.module.ts` file to import the `ForceLoadMfeModule`:

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import { ForceLoadMfeModule } from './force-load-mfe.module';

@NgModule({
  declarations: [AppComponent],
  imports: [BrowserModule, ForceLoadMfeModule],
  providers: [],
  bootstrap: [AppComponent],
})
export class AppModule {}

This file bootstraps the shell project and loads the MFE module forcibly.

Step 10: Run the Application

Run the following commands in separate terminal windows:

yarn serve shell
yarn serve mfe

This will start the shell project and MFE module in separate development servers.

Conclusion

In this comprehensive guide, we’ve shown you how to bootstrap the routing, NgRx, and other essential components of your MFE module from a shell project using Module Federation. By following these steps, you can create a scalable and maintainable Micro Frontend application with ease.

Keyword Description
Module Federation A technology that enables multiple modules to communicate and share resources in a Micro Frontend application.
MFE Module A Micro Frontend module that can be integrated with a shell project using Module Federation.
NgRx A state management library for Angular applications.
Routing A mechanism for navigating between components in an Angular application.

By following this guide, you’ll be able to create a highly scalable and maintainable Micro Frontend application using Module Federation, NgRx, and Angular. Happy coding!

Frequently Asked Question

Get ready to tackle the most pressing questions about bootstrapping the routing, NgRx, and more of MFE modules from the shell project using module federation!

What is the best approach to bootstrap the routing of an MFE module from the shell project?

To bootstrap the routing of an MFE module, you can create a separate routing module within the MFE module and then import it into the shell project’s app module. This way, you can configure the routing for the MFE module separately and then integrate it with the shell project’s routing.

How can I share state management between the shell project and MFE modules using NgRx?

To share state management between the shell project and MFE modules using NgRx, you can create a shared NgRx store that can be accessed by both the shell project and MFE modules. You can then use the @ngrx/store-devtools module to connect the MFE modules to the shared store.

Can I use the same instance of NgRx store across multiple MFE modules?

Yes, you can use the same instance of NgRx store across multiple MFE modules by creating a shared NgRx store in the shell project and then importing it into each MFE module. This way, all MFE modules can access the same state management instance.

How do I handle routing between MFE modules and the shell project?

To handle routing between MFE modules and the shell project, you can use the RouterModule.forRoot() method in the shell project to define the main routing configuration. Then, in each MFE module, you can use the RouterModule.forChild() method to define the routing configuration for that module.

What is the recommended way to load MFE modules lazily using module federation?

The recommended way to load MFE modules lazily using module federation is to use the webpack ModuleFederationPlugin to define the remotes and the exposures. Then, in your shell project, you can use the import() function to lazily load the MFE modules as needed.