[Micro frontends] Getting Started

blminami

Narcisa

Posted on February 10, 2023

[Micro frontends] Getting Started

At the beginning of this week, I took a course on micro frontends architecture topic. It's such a buzzword when it comes to frontend development, but I've never attempted anything in practice until this week.

Table of contents

  1. Introduction
  2. Application architecture
  3. Prerequisites
  4. Step-by-step tutorial
  5. Conclusion
  6. Additional resources

Introduction

When it comes to microservices, the backend services have this architecture in place for several years already. So why not taking advantage of all the benefits and start developing micro applications / micro components that can be owned, developed, managed and maintained by different teams. Of course, that's only one of the advantages (vertical teams that will handle a feature end-to-end), but we can also talk about the ability to scale the product by working on different features / modules in parallel, speed of delivery, support for innovation and new technologies, more reliable testing and maximum decoupling.

Let's see how it goes in practice!

Application architecture

I've decided to start from the well-known Angular Tour of Heroes tutorial and split the codebase into micro apps. There are a few approaches when it comes to splitting monolithic applications into micro frontends, I chose to do it by feature. The application provides two major features:

  • dashboard: top heroes + search heroes capability
  • heroes: list of heroes + hero management capabilities (view here, add hero, delete hero)

Tour of heroes dashboard page

Tour of heroes hero page

Considering the split by feature, I've decided on the following architecture of my application:

Tour of heroes architecture

where:

  • shell application is the app that will host all the remote micro applications (dashboard and heroes) and will handle everything related to the navigation (navigation component and routing logic)
  • dashboard micro application is one of the remote applications, targeting the dashboard feature
  • heroes micro application is the second remote application, targeting the heroes feature

Prerequisites for Angular micro frontends:

  • NodeJs 10.13.0+
  • Webpack 5
  • Angular 12+
  • NX

Step-by-step tutorial

🔸 download the Angular Tour of Heroes application
🔸 open terminal to the root directory and run

npm i && npm install -g nx
Enter fullscreen mode Exit fullscreen mode

🔸 transform the Angular cli workspace to an integrated NX monorepository (all the micro frontends will be part of the NX monorepo for simplicity)

ng add @nrwl/angular@<version_number>
Enter fullscreen mode Exit fullscreen mode

🔸 get rid of all the unused files, configs, packages and components to keep it simple and focus on the micro apps (remove the message component and e2e files)
🔸 run the application locally to check that all the changes made so far didn't affect the app

npx nx build tour-of-heroes
Enter fullscreen mode Exit fullscreen mode

So far, you should be able to navigate to http://localhost:4200 and check the application in the browser.

Let's keep having fun:

🔸 generate NX Angular application for dashboard-microapp and hero-microapp using nx cli

npx nx generate @nrwl/angular:app dashboard-microapp
Enter fullscreen mode Exit fullscreen mode
npx nx generate @nrwl/angular:app heroes-microapp
Enter fullscreen mode Exit fullscreen mode

🔸 add angular module federation plugin to all apps (shell, dashboard, hero)

npx nx g @angular-architects/module-federation:init 
--project tour-of-heroes --port 4200 --type host
Enter fullscreen mode Exit fullscreen mode
npx nx g @angular-architects/module-federation:init 
--project dashboard-microapp --port 4201 --type remote
Enter fullscreen mode Exit fullscreen mode
npx nx g @angular-architects/module-federation:init 
--project heroes-microapp --port 4202 --type remote
Enter fullscreen mode Exit fullscreen mode

This command will do a couple of things: add webpack.config.js, webpack.prod.config.js, bootstrap.js files and additional configurations (more details here)

The apps folder should look like this:

Application folder

🔸 let's consider the dashboard-microapp (same will apply to hero-microapp). At this point, in src folder, you have an Angular app configuration - with app.module, app.component.ts, app.component.html and app.component.css. We're going to create a new component, module and routing for the Dashboard feature

ng generate module dashboard --project=dashboard-microapp
Enter fullscreen mode Exit fullscreen mode

🔸 move the logic from the initial application (dashboard and hero-search components) to the dashboard application (you can copy paste the components and update the imports in case the IDE doesn't handle it)
🔸 configure the dashboard.module.ts as follow (by importing modules, declaring routes and components):

export const remoteRoutes: Route[] = [ 
  { path: '', component: DashboardComponent }, 
];

@NgModule({ 
  imports: [ 
    CommonModule, 
    HttpClientModule, 
    FormsModule, 
    RouterModule.forChild(remoteRoutes), 
  ], 
  declarations: [DashboardComponent, HeroSearchComponent], 
}) 
export class DashboardModule {}
Enter fullscreen mode Exit fullscreen mode

🔸 expose DashboardModule in webpack.config.js:

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

module.exports = withModuleFederationPlugin({ 
  name: 'dashboard-microapp', 
  filename: 'remoteEntry.js', 
  exposes: { 
    './Module': 
      './apps/dashboard-microapp/src/app/dashboard/dashboard.module.ts', 
  }, 
});
Enter fullscreen mode Exit fullscreen mode

🔸 now that you got the functionality moved to the micro-app and the module configured for this feature, update the app.module.ts:

@NgModule({ 
  declarations: [AppComponent], 
  imports: [ 
    BrowserModule, 
    HttpClientModule, 
    // optional: setting in-memory-web-api for microapps so we can test them separately 
    HttpClientInMemoryWebApiModule.forRoot(InMemoryDataService, { 
      dataEncapsulation: false, 
    }), 
    RouterModule.forRoot( 
      [ 
        { 
          path: '', 
          loadChildren: () => 
            import('./dashboard/dashboard.module').then( 
              (m) => m.DashboardModule 
            ), 
        }, 
      ], 
      { initialNavigation: 'enabledBlocking' } 
    ), 
  ], 
  providers: [], 
  bootstrap: [AppComponent], 
}) 
export class AppModule {}
Enter fullscreen mode Exit fullscreen mode

To test everything related to dashboard-microapp, let's run it in the browser and see what we get:

npm start dashboard-microapp
Enter fullscreen mode Exit fullscreen mode

navigate to http://localhost:4201 and you should be able to see the dashboard app:

Image description

🔸 repeat the same steps for hero-microapp (generate module, move functionality, update hero.module.ts file and app.module.ts, run it in browser and check that everything works as expected).

So far, we have 2 microapps that are running independently in the browser, how do we integrate them into the shell application so we can create the illusion of a single application for the end user?

🔸 switch to shell application (tour-of-heroes) and adjust webpack.config.js:

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

module.exports = withModuleFederationPlugin({ 
  remotes: {}, 
  shared: { 
    ...shareAll({ 
      singleton: true, 
      strictVersion: true, 
      requiredVersion: 'auto', 
    }), 
  }, 
});
Enter fullscreen mode Exit fullscreen mode

keep remotes: {} for dynamic consumption of micro applications

🔸 load the micro apps lazily when it's routed to:

const routes: Routes = [ 
  { 
    path: '', 
    loadChildren: () => 
      loadRemoteModule({ 
        remoteEntry: 'http://localhost:4201/remoteEntry.js', 
        type: 'module', 
        exposedModule: './Module', 
      }).then((m) => m.DashboardModule), 
  }, 
  { 
    path: 'heroes', 
    loadChildren: () => 
      loadRemoteModule({ 
        remoteEntry: 'http://localhost:4202/remoteEntry.js', 
        type: 'module', 
        exposedModule: './Module', 
      }).then((m) => m.HeroesModule), 
  }, 
];
Enter fullscreen mode Exit fullscreen mode

🔸 run all the applications

npm run run:all
Enter fullscreen mode Exit fullscreen mode

and navigate to http://localhost:4200. You should be able to see the Tour of heroes application - same as in the beginning, because nothing changed for the end user.

Hoooray! That was it! 🥳

Conclusion

This is my first attempt at micro frontends, I hope it clarifies the initial steps and configuration of the micro frontend architecture and encourages you to consider it for your future projects. I'll keep playing with it and document my stories while learning new stuff, so stay tuned! ^_^

Additional resources:

Until next time, thank you for reading! 🐾

💖 💪 🙅 🚩
blminami
Narcisa

Posted on February 10, 2023

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related