DEV Community

Narcisa
Narcisa

Posted on • Updated on

[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! ๐Ÿพ

Oldest comments (0)