Micro-Frontends

  1. What are Micro-Frontends?
  2. History of app development.
  3. Core Idea Behind Micro-Frontends.
  4. Advantages And Disadvantages.
  5. MF Frameworks.
  6. Module Federation

Micro-Frontends - What Are They?

Relatively new concept that extends the idea of Microservices to the frontend.

General idea behind the Micro-Frontend is to split one frontend application into multiple so that they can be worked on and deployed separately.

Monolith Frontend - One big application.

Micro-Frontends - Multiple small applications.

History Of App Development

At first, apps were monolith and contained both frontend and backend application.

They would later be split vertically to frontend and backend.

Backend applications were then split horizontally into microservices.

History Of App Development

At first, apps were monolith and contained both frontend and backend application.

They would later be split vertically to frontend and backend.

Backend applications were then split horizontally into microservices.

Core Idea Behind Micro-Frontends

The idea behind Micro-Frontends follows the idea behind microservices.

After splitting monolith frontend, the entire application is split horizontally which allows each team independent End-to-End development.

Core Idea Behind Micro-Frontends

The idea behind Micro-Frontends follows the idea behind microservices.

After splitting monolith frontend, the entire application is split horizontally which allows each team independent End-to-End development.

Advantages And Disadvantages

Adventages:

   1. Technology agnostic - different Micro-Frontends can use different programming languages,  frameworks and libraries.

   2. Loosely coupled - change in one Micro-Frontend does not require change in oters.

   3. Independent deployment - each MF-end can be deployed separately, independent of others.

Disadvantages:

   1. Complexity

   2. An emerging developer community

   3. No standards

MF Frameworks

Most popular MF frameworks:

  1. Bit

  2. Module Federation

  3. Single SPA

  4. Open Components

Module Federation

Module Federation is made out of 2 types of MF-end applications, host(shell) and remotes.

Host application is used as "backbone" and loads MF-ends when needed.

Module Federation

Module Federation is made out of 2 types of MF-end applications, host(shell) and remotes.

Host application is used as "backbone" and loads MF-ends when needed.

NX Library

# NX LIBRARY
  • tool for building enterprise-scale applications with Angular
  • faster builds
  • minimize the downsides that come with Module Federation

Create a new NX workspace

npx create-nx-workspace@latest wedofinance

Create a shell application

npx nx g @nrwl/angular:host shell --dynamic

Create a microfrontend application

npx nx g @nrwl/angular:remote excels --host=shell
...

Create library for shared code between shell and remotes

nx g @nrwl/angular:lib shared/auth
...
# NX LIBRARY

Generated files:

  • standard Angular application files
  • project.json (updated the build target - @nrwl/angular:webpack-browser)
  • webpack.config.js
  • module-federation.config.js
  • bootstrap.ts
# NX LIBRARY
//apps/shell/webpack.config.js

const withModuleFederation = require('@nrwl/angular/module-federation');
const moduleFederationConfig = require('./module-federation.config');

module.exports = withModuleFederation({
  ...moduleFederationConfig,
});
//apps/shell/module-federation.config.js

module.exports = {
  name: 'shell',
  remotes: [],	//dinamicki
  //remotes: ['excels', 'transactions', 'graphs'], //staticki
};
//apps/excels/module-federation.config.js

module.exports = {
  name: 'excels',
  exposes: {
    './Module': 'apps/excels/src/app/remote-entry/entry.module.ts',
  },
};
# NX LIBRARY

Communication

# COMMUNICATION
  • module-federation.manifest.json
  • remotes.d.ts
  • main.ts (shell)
  • app.routes.ts
  • module-federation.config.js
  • entry.routes.ts (microfrontents)
  • index.ts (lib)
//module-federation.manifest.json
{
  "excels": "http://localhost:4201",
  "transactions": "http://localhost:4202",
  "graphs": "http://localhost:4203"
}
  
//main.ts - shell
import { setRemoteDefinitions } from '@nrwl/angular/mf';
fetch('/assets/module-federation.manifest.json')
  .then((res) => res.json())
  .then((definitions) => setRemoteDefinitions(definitions))
  .then(() => import('./bootstrap').catch((err) => console.error(err)));
  

manifest.json, remote.d.ts and main.ts

//remotes.d.ts
declare module 'excels/Module';
declare module 'transactions/Module';
declare module 'graphs/Module';
  
# COMMUNICATION
//app.routes.ts - shell
export const appRoutes: Route[] = [
  {
    path: 'excels',
    loadChildren: () =>
      loadRemoteModule('excels', './Module').then((m) => m.RemoteEntryModule),
  }, ...
];
  
//app.routes.ts - microfrontend
export const remoteRoutes: Route[] = [
  {
    path: '',
    loadChildren: () => import('../excel-upload/excel-upload.module')
    .then(m => m.ExcelUploadModule)
  },
  {
    path: 'approval',
    loadChildren: () => import('../excel-approval/excel-approval.module')
    .then(m => m.ExcelApprovalModule)
  },
];
  

app.routes.ts

# COMMUNICATION
//index.ts - library
export * from './lib/shared-excel-lib.module';
export * from './lib/services/excel.service';
export * from './lib/services/upload-excel.service';
  

Important to add exports in library's index.ts so each new class can be accessible from outside of library

index.ts

# COMMUNICATION

Docker Containers

To use docker with MF application it is necessary to create docker container for each MF-end.

 

To create MF-end container we need to write Dockerfile as well as docker-compose file for it.

 

wedofinance-graphs.yml file

version: "3.8"
services:
#----------------------------------------------------------------
  wedofinance-graphs:
    build: 
      context: ./../wedofinance-frontend
      dockerfile: apps/graphs/Dockerfile
    container_name: wedofinance-graphs
    restart: on-failure
    expose:
      - '4203'
    ports:
      - "4203:80"
    networks:
      - wedofinance-network
#----------------------------------------------------------------
networks:
  wedofinance-network:
YML file example

Graphs Dockerfile

FROM node:latest as node
WORKDIR /app
COPY . .


RUN npm install -g @nrwl/cli
RUN npm install --force
RUN npx nx build graphs --configuration=production

#stage 2
FROM nginx:alpine
COPY ./apps/graphs/nginx.conf /etc/nginx/nginx.conf
COPY --from=node app/dist/apps/graphs /usr/share/nginx/html
Dockerfile example

Nginx config file

events{}
http {
    include /etc/nginx/mime.types;
    server {
        listen 80;
        server_name localhost;
        root /usr/share/nginx/html;
        index index.html;
	add_header Access-Control-Allow-Origin *;
        location / {
            try_files $uri $uri/ /index.html;
        }
    }
}
Nginx config 

Problems in Dockerization

# PROBLEMS
Failed to fetch module due to MIME mismatch

Failed to fetch module due to MIME mismatch

Solution:

# PROBLEMS

Solution:

# PROBLEMS

Adding MIME types to Nginx config file:

events{}
http {
    include /etc/nginx/mime.types;
    server {
        listen 80;
        server_name localhost;
        root /usr/share/nginx/html;
        index index.html;
	add_header Access-Control-Allow-Origin *;
 	types 
    	{
             text/html                                        html htm shtml;
    	     text/css                                         css scss;
             text/xml                                         xml;
             image/gif                                        gif;
             image/jpeg                                       jpeg jpg;
             application/javascript                           js mjs;
             application/atom+xml                             atom;
             application/rss+xml                              rss;
    	}
        location / {
            try_files $uri $uri/ /index.html;
        }
    }
}

Source:

Module Federation

By Mitar Brankovic

Module Federation

  • 151