Hi, I am Trishul

🤖

 

👨‍💻

 

Destructuring Frontend monoliths with MicroFrontends

@trishulgoel

Monoliths

Monolithic application is designed to be self-contained; components of the program are interconnected and interdependent

Frontend Monolith

All the code in a single place

Increased inter-team dependency

Slow development to deploy cycle

Increasing size of repo everyday

Only as strong as weakest link

MICROFRONTENDS

Microfrontend architecture is a design pattern where a monolithic Frontend app is destructured into small independent(?) apps. These micro apps are stitched together as a single page on the fly.

Standalone system

Independent Repository

Independent CI Pipelines

Independent Deployments

Parallel development cycle

ARCHITECTURE

Remote 1

HOST

Remote 2

Remote 3

HEADER

FOOTER

Home Page

Product Listing

Page

Product Details

Page

Payments

and

Checkout

Cart

MicroFrontend

Appshell / Host

Appshell

Shared business Logic

Login

Tracking

System config

Routing

COMMUNICATION

Same tech stack

Share as params

Different tech stack

Custom DOM events

Custom DOM Events

HOW?

Some Traditional Approaches

Node modules

IFrames

MODULE FEDERATION

Remote 1

Remote 2

Remote 3

HOST

shared.component.ts

    import { Component, OnInit } from '@angular/core';

    @Component({
        selector: 'app-shared-component',
        templateUrl: './sharedModule.component.html',
        styleUrls: ['./sharedModule.component.css']
    })

    export class SharedComponent implements OnInit {
        constructor() {}

        ngOnInit(): void {}
    }

Remote config

    new ModuleFederationPlugin({
        name: "remote",
        filename: "remoteEntry.js",
        exposes: {
            './SharedModule': './src/app/shared/sharedModule.component.ts',
        },        
        shared: {
          "@angular/core": { singleton: true, strictVersion: true }, 
          "@angular/common": { singleton: true, strictVersion: true }, 
          "@angular/router": { singleton: true, strictVersion: true },
        }
    }),

Host config

	new ModuleFederationPlugin({
        remotes: {
            "remote": "remote@http://localhost:4300/remoteEntry.js",
        },
        shared: {
          "@angular/core": { singleton: true, strictVersion: true }, 
          "@angular/common": { singleton: true, strictVersion: true }, 
          "@angular/router": { singleton: true, strictVersion: true },
        }
    }),

Host App

    import { NgModule } from '@angular/core';
    import { RouterModule, Routes } from '@angular/router';
    import { SharedComponent } from 'remote/SharedModule';

    const routes: Routes = [
      {
        path: 'remote',
        component: SharedComponent,
        data: { from: ' Host' }
      },
    ];

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

DEMO TIME

CHALLENGES

DESIGN CONSISTENCY

Initializing new MicroFrontend

Templating engine

Tenpureto

Moving components to design system

Sharing logic between Micro Frontends

Building an efficient developer experience

Decoupling code from Appshell

THANK YOU

@trishulgoel

REFERENCES

  • https://webpack.js.org/concepts/module-federation/

  • https://github.com/module-federation/module-federation-examples

MicroFrontends | AngularDay

By Trishul Goel

MicroFrontends | AngularDay

Destructuring Frontend Monoliths with MicroFrontends

  • 746