Insights on Micro Frontends Architecture with Angular and Web Components

In this article I will present a solution and share my thoughts and experience regarding how to implement components in a distributed manner, considering the issues that can present during the development process.
Micro-Frontend Architecture
Imagine you have a platform that consists of a suite of web applications, all of which may have been developed with the same technology stack. You create a shared npm library to centralize the development of the common components, then you update the components in a single place and publish a new version of the library so that all your applications can use it.
Everything looks great until you realize the applications don’t receive the updates automatically, so you have to update the library version in the.json package of all the applications one by one and deploy them to implement the latest changes. If there is a hotfix or a new feature that has to be applied to all the applications, you have to repeat the process.

The problem

Lets visualize the real problem, all our applications share a common theme layout that includes a header with some widgets/components, maybe some shared menus, and a footer for all the applications.
This layout can be created easily in a common npm library, but maybe the different widgets are complex components and are being developed by different teams, with all the potential issues that this implies, such as bugs, new features, or contract changes.

The proposed solution - Web components

The idea is to create each widget as a web component that can be deployed independently as a .js file, after which the applications can load and render them in the placeholders created for them in the theme layout.


For the implementation I’m going to talk about two applications, first the main angular application which could be one of the applications from my suite, which we’ll call WrapperApp. We need to install some dependencies and consider how to load the web components.
Second is the WidgetComponent. I’m going to use some libraries here to customize the usual Angular build with the required considerations.




You can follow the official documentation of @angular-extensions/elements which you can see here:, but here’s a simple example.
selector: 'wrapper-app-component',
template: `

export class WrapperComponent {
elementUrl = 'http://localhost:5001/main.js';

data = {};

handleChange(change) {
And that’s it, your widget component will be loaded just like that.




Angular documentation has a section on the creation of web components. They call them Angular Elements, and you can check it out here: Following this guide, the AppComponent of our WidgetComponent should look like this
import { BrowserModule } from '@angular/platform-browser';
import { NgModule, Injector } from '@angular/core';
import { createCustomElement } from '@angular/elements';

import { AppComponent } from './app.component';
import { WidgetComponent} from './widget-component/widget-component.component';

declarations: [
imports: [
providers: [],
entryComponents: [
export class AppModule {
constructor(private injector: Injector) { }
ngDoBootstrap(): void {
const { injector } = this;
const ngCustomElement = createCustomElement(WidgetComponent, { injector });
customElements.define('widget-component', ngCustomElement);

It is important to note first of all that the NgModule definition doesn’t have a Bootstrap component, and secondly, that in the ngDoBootstrap method the “widget-component” tag name that you choose must be the same as the one that you are going to use in the wrapper app with the axLazyElement directive.


In the Angular.json, replace the default builder with ngx-build- plus:
"architect": {
"build": {
"builder": "ngx-build-plus:build", ....
"serve": {
"builder": "ngx-build-plus:dev-server",
"test": {
"builder": "ngx-build-plus:karma",
You can define two custom scripts in your.json package file
"start": "npm run build && serve -l 5001 dist/micro-fe-ng",
"build": "ng build --prod --output-hashing none --single-bundle true",
The first one will be useful during development, and the second will probably be needed to build the component. Your continuous deployment tool may use it, and it ensures that the resulting build is in a single file and that the name is fixed, so you can always load the same file name.

Final Thoughts

Emiliano Daza

About the Author

Emiliano Daza is a Full Stack developer specialized in JavaScript, with 8 years of experience in software development. Emiliano shows good effort and team collaboration and always delivers high-quality results. He has excellent communication skills.