What is mincrofrontend in angular explain with examples in code

 Micro-frontend architecture in Angular involves breaking down a large monolithic frontend application into smaller, independently deployable applications. This approach enhances scalability, flexibility, and maintainability, allowing teams to work on different parts of the application simultaneously.

In a micro-frontend setup, each micro-frontend can be developed and deployed independently, often using different technologies or frameworks. The integration of these micro-frontends is typically managed by a shell application, which handles routing and shared state.

Key Concepts of Micro-Frontends in Angular

  • Independent Deployability: Each micro-frontend can be developed, tested, and deployed independently, allowing for faster release cycles.

  • Team Autonomy: Different teams can work on different micro-frontends without interfering with each other, promoting parallel development.

  • Shared Libraries: Common functionalities and components can be shared across micro-frontends through shared libraries.

  • Routing: The shell application manages routing to load the appropriate micro-frontend based on the URL.

Example Implementation

  1. Setting Up the Shell Application: Create a new Angular application that will serve as the shell for your micro-frontends.

    bash
    1ng new shell-app 2cd shell-app
  2. Defining Routes in the Shell: In the app-routing.module.ts, define routes for the micro-frontends.

    typescript
    1import { NgModule } from '@angular/core'; 2import { RouterModule, Routes } from '@angular/router'; 3 4const routes: Routes = [ 5 { path: 'micro-frontend1', loadChildren: () => import('micro-frontend1/Module').then(m => m.MicroFrontend1Module) }, 6 { path: 'micro-frontend2', loadChildren: () => import('micro-frontend2/Module').then(m => m.MicroFrontend2Module) }, 7 { path: '', redirectTo: '/micro-frontend1', pathMatch: 'full' } 8]; 9 10@NgModule({ 11 imports: [RouterModule.forRoot(routes)], 12 exports: [RouterModule] 13}) 14export class AppRoutingModule { }
  3. Creating Micro-Frontend Applications: Generate separate Angular applications for each micro-frontend.

    bash
    1ng new micro-frontend1 2ng new micro-frontend2
  4. Configuring Webpack Module Federation: In each micro-frontend, configure Webpack Module Federation to expose components.

    javascript
    1const ModuleFederationPlugin = require("webpack/lib/container/ModuleFederationPlugin"); 2 3module.exports = { 4 output: { 5 publicPath: "http://localhost:4201/", 6 uniqueName: "micro-frontend1" 7 }, 8 plugins: [ 9 new ModuleFederationPlugin({ 10 name: "micro-frontend1", 11 filename: "remoteEntry.js", 12 exposes: { 13 './Module': './src/app/app.module.ts', 14 }, 15 shared: { 16 "@angular/core": { singleton: true, strictVersion: true }, 17 "@angular/common": { singleton: true, strictVersion: true }, 18 "@angular/router": { singleton: true, strictVersion: true }, 19 } 20 }) 21 ], 22};
  5. Integrating Micro-Frontends in the Shell: In the shell application, configure the Module Federation Plugin to load the micro-frontends.

    javascript
    1const ModuleFederationPlugin = require("webpack/lib/container/ModuleFederationPlugin"); 2 3module.exports = { 4 output: { 5 publicPath: "http://localhost:4200/", 6 uniqueName: "shell-app" 7 }, 8 plugins: [ 9 new ModuleFederationPlugin({ 10 remotes: { 11 "micro-frontend1": "micro-frontend1@http://localhost:4201/remoteEntry.js", 12 "micro-frontend2": "micro-frontend2@http://localhost:4202/remoteEntry.js" 13 }, 14 shared: { 15 "@angular/core": { singleton: true, strictVersion: true }, 16 "@angular/common": { singleton: true, strictVersion: true }, 17 "@angular/router": { singleton: true, strictVersion: true }, 18 } 19 }) 20 ], 21};
  6. Running the Applications: Ensure all applications are running to see the integration in action.

    bash
    1ng serve --project shell-app 2ng serve --project micro-frontend1 3ng serve --project micro-frontend2

    Visit http://localhost:4200 to see the shell application load the micro-frontends as configured.

Conclusion

Micro-frontend architecture in Angular allows for a modular approach to building applications, enabling teams to work independently while still delivering a cohesive user experience. By leveraging tools like Webpack Module Federation, developers can create scalable and maintainable applications that can evolve over time.


Another examples and details : 

Microfrontends in Angular: An Introduction

Microfrontends is an architectural approach where a frontend application is broken down into smaller, independent, and manageable pieces called "microfrontends." Each microfrontend is typically a feature or module within a larger app, developed and deployed independently. These microfrontends can be written in different technologies, have their own build pipeline, and can be developed and maintained by separate teams. The goal is to improve scalability, maintainability, and collaboration in large web applications.

In Angular, the concept of microfrontends is commonly implemented by creating multiple Angular applications or modules, each responsible for a specific feature of the frontend. These applications are then combined into a single frontend app (host app) that can load and render them on demand.

Why Use Microfrontends in Angular?

  1. Scalability: Large teams can work on separate parts of the application without affecting each other.
  2. Independent Deployment: Each microfrontend can be deployed independently, allowing faster and more frequent releases.
  3. Technology Agnostic: Different microfrontends can be built with different technologies if needed.
  4. Maintainability: Smaller, isolated codebases are easier to maintain.

Steps to Implement Microfrontends in Angular

Let’s break down the process of creating a microfrontend architecture in Angular with a single host application and multiple microfrontend applications.

We'll use Module Federation to implement the microfrontend structure, which is a Webpack feature that allows dynamic loading of JavaScript modules from remote sources. This allows one Angular app to load another app at runtime.

1. Set up the Angular Applications

Let’s assume we have the following Angular applications:

  • Host Application: The main app where we will integrate all the microfrontends.
  • Microfrontend 1 (User Profile): A microfrontend for the user profile page.
  • Microfrontend 2 (Dashboard): A microfrontend for the dashboard page.
  • Microfrontend 3 (Settings): A microfrontend for the settings page.

You can create these Angular applications using the Angular CLI:

bash
ng new host-app ng new user-profile-app ng new dashboard-app ng new settings-app

2. Configure Webpack Module Federation

To make the integration work, we'll use Webpack Module Federation. In the angular.json file of each microfrontend app, configure Webpack to expose specific modules (components, services, etc.), and configure the host app to load them.

Configure Module Federation in Microfrontends

For example, in the user-profile-app:

  1. Install Webpack Module Federation dependencies in each Angular project:
bash
npm install @angular-architects/module-federation --save-dev
  1. In webpack.config.js (or create it), set up the module federation configuration:
javascript
module.exports = { output: { uniqueName: 'userProfileApp', publicPath: 'auto', }, optimization: { runtimeChunk: false }, plugins: [ new ModuleFederationPlugin({ name: 'userProfileApp', filename: 'remoteEntry.js', // This file will be loaded by the host app exposes: { './UserProfile': './src/app/user-profile/user-profile.module.ts', // Expose the user profile module }, shared: ['@angular/core', '@angular/common', '@angular/router'], }) ] };

You would do a similar configuration for the dashboard-app and settings-app.

Configure Module Federation in the Host Application

In the host-app, configure Webpack to dynamically load the microfrontends:

javascript
module.exports = { output: { uniqueName: 'hostApp', publicPath: 'auto', }, optimization: { runtimeChunk: false }, plugins: [ new ModuleFederationPlugin({ name: 'hostApp', remotes: { userProfileApp: 'userProfileApp@http://localhost:4201/remoteEntry.js', // URL to user profile app dashboardApp: 'dashboardApp@http://localhost:4202/remoteEntry.js', // URL to dashboard app settingsApp: 'settingsApp@http://localhost:4203/remoteEntry.js', // URL to settings app }, shared: ['@angular/core', '@angular/common', '@angular/router'], }) ] };

3. Load the Microfrontends in the Host Application

In the host application, we now need to load the microfrontends dynamically using Angular routing and lazy loading.

First, set up Angular routing in the host app to load each microfrontend:

typescript
const routes: Routes = [ { path: 'user-profile', loadChildren: () => import('userProfileApp/UserProfile').then((m) => m.UserProfileModule), }, { path: 'dashboard', loadChildren: () => import('dashboardApp/Dashboard').then((m) => m.DashboardModule), }, { path: 'settings', loadChildren: () => import('settingsApp/Settings').then((m) => m.SettingsModule), }, { path: '', redirectTo: '/dashboard', pathMatch: 'full', }, ];

Here, loadChildren uses dynamic imports to fetch the microfrontend modules, which are exposed by the respective microfrontend apps.

4. Microfrontend Communication

If your microfrontends need to communicate with each other, you can use shared services or an event-based system like RxJS to share data between the microfrontends. For instance, you can have a shared service in the host app that passes data to each microfrontend.

Example of a shared service:

typescript
// shared-data.service.ts in host app import { Injectable } from '@angular/core'; import { BehaviorSubject } from 'rxjs'; @Injectable({ providedIn: 'root' }) export class SharedDataService { private dataSubject = new BehaviorSubject<string>('Initial Data'); data$ = this.dataSubject.asObservable(); updateData(newData: string) { this.dataSubject.next(newData); } }

In the microfrontend:

typescript
// In user-profile-app or dashboard-app import { SharedDataService } from 'host-app/shared-data.service'; @Component({ selector: 'app-user-profile', templateUrl: './user-profile.component.html', styleUrls: ['./user-profile.component.css'] }) export class UserProfileComponent { data: string; constructor(private sharedDataService: SharedDataService) { this.sharedDataService.data$.subscribe((data) => { this.data = data; }); } }

5. Run the Applications

Now, you can run each microfrontend and the host application. Make sure to run them on different ports so they can be loaded into the host app.

For example:

  • Run the user-profile-app on localhost:4201
  • Run the dashboard-app on localhost:4202
  • Run the settings-app on localhost:4203
  • Run the host-app on localhost:4200

Once you navigate to different URLs in the host app (e.g., /user-profile, /dashboard, /settings), the corresponding microfrontend will be loaded dynamically.


Summary

  • Microfrontends split a large frontend application into smaller, independent apps, each responsible for a specific feature or section.
  • Angular apps can be integrated into a microfrontend architecture using Webpack Module Federation.
  • The host application dynamically loads the microfrontends using Angular's lazy loading feature.
  • Microfrontends can communicate using shared services or event-based systems like RxJS.
  • Each microfrontend can be developed and deployed independently, allowing for faster releases and easier maintenance.

By adopting the microfrontend approach, you can scale large Angular applications, improve team collaboration, and optimize deployment cycles.

Comments

Popular posts from this blog

PrimeNG tutorial with examples using frequently used classes

Docker and Kubernetes Tutorials and QnA

Building strong foundational knowledge in frontend development topics