Angular — Micro-Frontend

Everything you need to know about microservice oriented architecture for the frontend from beginner to advanced

Ahmed Bouhlel
Dev Genius

--

Modern web applications are becoming big and more complex and sometimes managed by different teams. Your application might have features developed by different teams and you want to release only certain features into production before delivering the entire application. How do you manage different teams, different release timelines if you have one repo?

Most of these complex apps live on the client side which makes it harder to maintain. There are some other issues as well with this monolithic big fat application. In this post, I am going to discuss advantages, disadvantages, implementation and a lot of other stuff.

  • Introduction
  • A Journey Into Mirco-Frontends
  • Advantages of Mirco-Frontends
  • Features of Mirco-Frontends
  • How Do We Split Apps
  • Different Approaches to Micro-Frontends
  • Micro-Frontend Frameworks
  • Example Micro-frontend Project With Angular
  • Summary
  • Conclusion

Introduction

Micro-frontends are small applications mostly divided by subdomain or functionality working together to deliver a larger application. Before diving into Mirco-frontends, we will understand what are micro frontends and why we are talking about those.

Usually, projects come in different sizes and different requirements. If your project is simple enough to have two or three pages and can be maintained by a single team, you don’t have to think about these Micro-frontends. You can just implement with any of your chosen frameworks such as Angular, React, or Vuejs.

But, this is not the case all the time. Sometimes your frontend app might be a small part of another big application or your app consists of a lot of sections and features which are developed by different teams or your app is being released into production feature by feature developed by separate teams. If you are in one of these situations then you need to think about Micro Frontends. Let’s look at it in the below diagram.

Micro Frontends Architecture
Micro Frontends Architecture

As you see in the above diagram, we have 6 frontend apps working together to deliver the large application. The communication between these apps can be done with an event bus, window object, or publish/subscribe methods. Each app can be implemented by a separate team and any framework. Each app can talk to its backends or endpoints individually. There is a bootstrap/launch app that loads all the apps and mounts and unmounts in the DOM depending on the user interaction or routing.

A Journey Into Micro-Frontends: We will first understand why do we need this in the first place. Let’s have a look at the present technologies that we use for user-faced web applications.

Advantages of Micro-Frontends: Here are the advantages of this architecture.

Apps are small: Obviously, apps become small when we split the large application by sections, pages or features.

Apps are independent: Since all the apps are divided and developed separately these are independent of each other

Apps are easier to understand: Apps are easier to understand because they are small and developed by a single team.

Apps are easier to develop and deploy: As these apps are small in nature and developed by a single team it's very easy to develop and deploy. We can even deploy independently.

Apps are easier to test: We have to write thousands and thousands of unit tests for larger applications and takes forever to run. This makes out deployment process slower. When it comes to micro frontends each app has a few unit tests and executes its own unit tests and can be run independently.

Apps development becomes faster: The whole development becomes faster and easier because of separate teams.

CI/CD Becomes easier: Each app can be integrated and deployed separately and this makes the CI/CD process a lot easier. When we fix the app or introduce a new feature we don’t have to worry about the entire application since all the features are independent.

Independent Stacks and versions: We can choose our own stack for each app but this doesn’t happen so often But, we can have different versions of the same stack. For example, Some teams have the flexibility and time to introduce and test newer versions of the same stack.

No Shared Code: In large applications, we tend to share code across features but, this doesn’t scale well and introduces a lot of bugs and interdependency as the app grows bigger and bigger. This doesn’t apply with the Micro-frontends as we do not share the code unless it is a dumb component.

Can change architecture easily without touching old one: Sometimes we have to extend the old architecture but we might not have the developers to implement or extend the architecture. With the Micro frontends approach, we can develop the new feature with the latest stack and deliver independently.

Features of Mirco-Frontends

  • Each frontend represents a specific feature or subdomain of the entire application
  • Each frontend can be implemented with a separate team.
  • Each frontend can be implemented with different technology.
  • They cannot share logic and its independent of each other.
  • Each Frontend can be owned by a single team.

How Do We Split Apps

Let’s see how we can split large applications into micro frontends. There are no specific criteria to divide the apps and we can separate in a number of ways depending on our needs. We will see all the possible ways that we could divide apps.

By Feature

This is the most common method since we can easily divide the features of the app. For example, if there are three features for the app Dashboard, Profile and views we can make each feature as a separate app and mounts and unmounts in the DOM with the help of Launch.js. This Launch.js can be a separate app or just a simple javascript app.

By Section

Some of the apps have so much functionality with each section, for example, coinbase, Gmail, etc. We can implement each section as a new app in that scenario.

By Page

Some app’s functionalities are divided by page. Each page has some functionality that can be independent. We can divide these apps by page We have four pages in the below diagram. we can make four apps out of this.

By Domain

Splitting app based on the domain is also one of the most common approaches.

By Domain
By Domain

Different Approaches to Micro-Frontends

There are many approaches that you could implement Micro-Frontends. But I found these 6 ways to implement.

  • Iframes
  • Through NGINX
  • Web Components/Angular Elements
  • Angular Libraries
  • Monorepos
  • Customized Orchestrator

Micro-Frontend Frameworks

Micro frontends have been implemented for at least two years and it is still a green field. Have you ever wondered are there any frameworks or libraries to implement these and make our job easier. The answer is yes and there are a couple of libraries or frameworks

single-spa

single-spa is a javascript framework for front-end microservices and can be implemented with all three popular frameworks/libraries such as Angular, React and Vue.js. It can lazy load the applications based on the need and You can check out their website for more information.

frint.js

frint.js is a Modular JavaScript framework for building Scalable & Reactive applications. It doesn’t support Angular yet but it supports React. If you are building a reactive application from scratch and you are just starting, this is the framework for you. You can check out their website for more information.

Example Micro-frontend Project With Angular

With all this information let’s build an example Angular project with the help of a single-spa framework. I would like to build a simple app for the demonstration and I will do the full example with all the features in another post.

We will split this app by section as shown in the below diagram. We are going to implement 4 apps in total: HeaderApp, DashboardApp, FooterApp, and root application.

Here are the four repositories for four apps. You can clone these run them separately on your machine.

// root app runs on port 4200
git clone https://github.com/ahmedbhl/micro-root.git
npm install
npm start

// micro header runs on port 4300
git clone https://github.com/ahmedbhl/micro-header.git
npm install
npm start

// micro dashboard runs on port 4202
git clone https://github.com/ahmedbhl/micro-dashboard.git
npm install
npm start

// micro footer runs on port 4201
git clone https://github.com/ahmedbhl/micro-footer.git
npm install
npm start

You can access the whole application on http://localhost:4200/

Running all four apps together to make it one app

Here is the micro-root app index HTML file. We are importing all three apps on line 10 and registering the apps with the appropriate name and location. Since we are loading all the apps on page load, we are not defining any specific context paths.

<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Security-Policy" content="default-src * data: blob: 'unsafe-inline' 'unsafe-eval'; script-src * 'unsafe-inline' 'unsafe-eval'; connect-src * 'unsafe-inline'; img-src * data: blob: 'unsafe-inline'; frame-src *; style-src * data: blob: 'unsafe-inline'; font-src * data: blob: 'unsafe-inline';">
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>Your application</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="importmap-type" content="systemjs-importmap">
<script type="systemjs-importmap">
{
"imports": {
"footer": "http://localhost:4201/main.js",
"dashboard": "http://localhost:4202/main.js",
"header": "http://localhost:4300/main.js",
"single-spa": "https://cdnjs.cloudflare.com/ajax/libs/single-spa/4.3.5/system/single-spa.min.js"
}
}
</script>
<link rel="preload" href="https://cdnjs.cloudflare.com/ajax/libs/single-spa/4.3.5/system/single-spa.min.js" as="script" crossorigin="anonymous" />
<script src='https://unpkg.com/core-js-bundle@3.1.4/minified.js'></script>
<script src="https://unpkg.com/zone.js"></script>
<script src="https://unpkg.com/import-map-overrides@1.6.0/dist/import-map-overrides.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/systemjs/4.0.0/system.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/systemjs/4.0.0/extras/amd.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/systemjs/4.0.0/extras/named-exports.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/systemjs/4.0.0/extras/named-register.min.js"></script>
<style>
</style>
</head>
<body>
<script>
System.import('single-spa').then(function (singleSpa) {
singleSpa.registerApplication(
'header',
function () {
return System.import('header');
},
function (location) {
return true;
}
)

singleSpa.registerApplication(
'dashboard',
function () {
return System.import('dashboard');
},
function (location) {
// return location.pathname.startsWith('/app2');
return true;
}
)

singleSpa.registerApplication(
'footer',
function () {
return System.import('footer');
},
function (location) {
// return location.pathname.startsWith('/app1');
return true;
}
);

singleSpa.start();
})
</script>
<import-map-overrides-full></import-map-overrides-full>
</body>
</html>

root app index.html

You can give /header location path so that the header is loaded when browser URL navigates to /header. Let’s test it out.

<script>
System.import('single-spa').then(function (singleSpa) {
singleSpa.registerApplication(
'header',
function () {
return System.import('header');
},
function (location) {
return location.pathname.startsWith('/header');
// return true;
}
)

with /header

Conclusion

I know Microfrontends is such a trendy thing but you should not use it for every app. Do not use it if your app is small and don’t complicate it. This approach should make our whole process seamless not over complicated. So use your best judgment before using this approach.

Thank you for reading and keep visiting !

If you found this article interesting and helpful, and you’re keen to dive deeper into Angular, consider supporting my work. You can buy me a coffee ☕️ to keep the content coming.

For regular updates on the latest in Angular — including news, signals, docker, spring, updates, and much more — follow me on X (formerly Twitter) @Ahmed_bouhlel . Your support and engagement are greatly appreciated !

--

--

Senior full-stack software enginering with extensive experience in multi programming languages, including Java, Angular& various modules of the Spring Framework