Creating Angular Web Components: A Micro Frontend Tutorial

SUBSCRIBE TO THE BLOG

It is common to find that the tech stack you choose to solve one problem does not work to solve another. Maybe your company is big enough to have different dev teams, each with a unique knowledge and focus on specific technologies. For example, you may have three teams that are familiar with React and three more teams that focus on Angular web components. So how do you choose which team to give new projects to? 

With micro frontends, you can combine different technologies within the same application, allowing for collaboration across different teams without forcing one to learn a new framework/language.

In this tutorial, we’re going to learn how to set up an Angular application to host different micro frontends and configure it as a web component capable of running in any browser and/or inside another Angular or React application.

Some key reasons to choose micro frontends over the traditional monolithic architecture are:

• The companies have different dev teams each one with specific knowledge for certain frameworks

• Multiple applications that can reuse the web component (ie. Login tab or Chat window)

•  The main application can continue running even if the internal web component fails

The majority of the projects in the frontend are monolithic. With micro frontend architecture, we can divide the web app into different web components, independent of each other, each one with its own development, test, and delivery processes.

This web architecture is tech agnostic, meaning every component can be written using a different framework, like Angular or React, enabling multiple teams to work in the same project by using the technology that best suits the component/feature. This helps increase browser compatibility, speed up the update, deploy, and resolve bugs without compromising the main app. 

Let’s look at an example. Facebook uses this kind of architecture on its website (see post):

 

Example FaceBook page, the chat function and news feed are different main window components. The main goal of micro frontends is to break the complete website into different web components that don’t affect the user experience, allowing the user to start interacting with the individual components as they load on the page.

As you can see in the picture above, the chat function and news feed are different main window components. The main goal of micro frontends is to break the complete website into different web components that don’t affect the user experience, allowing the user to start interacting with the individual components as they load on the page.

Now that we have an idea of how micro frontends work, let’s dive into a tutorial for creating Angular web components.

 

Creating an Angular Web Component with Ngx-build-plus

Step 1: Install Angular Cli

npm install -g @angular/cli

Step 2: Create a new project ({project-name}-wc-feature)

ng new phoenix-wc-wiki-ngx

When the terminal asks us, “Would you like to add Angular routing?” we choose “No.”

Step 3: Add the @angular/elements and ngx-build-plus

ng add @angular/elements
ng add ngx-build-plus

*To check if the installation was successful, go to the angular.json and check the property “builder” under architect → build, should be “builder”: “ngx-build-plus:browser”.

Step 4: Comment the bootstrap property in the @NgModule declaration`, add the AppComponent to entryComponents, and add the custom element in phoenix-wc-wiki-ngx/src/app/app.module.ts

Install Angular Cli. Create a new project ({project-name}-wc-feature). Comment the bootstrap property in the @NgModule declaration`, add the AppComponent to entryComponents, and add the custom element in phoenix-wc-wiki-ngx/src/app/app.module.ts

* To be able to use the AppComponent with ng serve and develop normally, you have to uncomment the bootstrap property in the @NgModule declaration phoenix-wc-wiki-ngx/src/app/app.module.ts. But do not forget to comment it when you are going to generate the build.

Step 5: Run the command to generate the build

ng build --prod --output-hashing none --single-bundle true


*If you get the following error: Schema validation failed with the following errors:Data path “.budgets[1].type” should be equal to one of the allowed values.

Step 6: Go to budgets in the angular.json and delete these lines:

Run the command to generate the build

Leaving only:

What code is left over after running the command to generate the build.

 

Step 7: Install Static-Server to test the component

npm i -g static-server

In the folder dist/phoenix-wc-wiki-ngx, create an index.html, adding the zone.min.js needed to run angular, webcomponents-bundle.js and custom-elements-es5-adapter.js, and polyfill.js to make it cross-browser compatible.

Install Static-Server to test the component.

 

Step 8: Run the command in the folder dist/phoenix-wc-wiki-ngx

Go to http://localhost:9080/ and you should see:

static-server

 

Run the command in the folder dist/phoenix-wc-wiki-ngx . Go to http://localhost:9080/ and you should see:

Step 9: Repeat the same process to create another web component called phoenix-wc-wiki-ngx-lt

Step 10:  Now we have two web components. To test them together, change some of the build files from main-es5.js to{project-name}-bundle.js.

Step 11: To test that both web components are working together, add the files *bundle.js to the same folder and change the index.html use for the static-server like this:

Repeat the same process to create another web component called phoenix-wc-wiki-ngx-lt. Now we have two web components. To test them together, change some of the build files from main-es5.js to{project-name}-bundle.js. To test that both web components are working together, add the files *bundle.js to the same folder and change the index.html use for the static-server

If you refresh the http://localhost:9080/, you will see something like:

The refresh page after.

You can see that now we have both web components on the same page.

 

Adding Initial Parameters to the Web Component

Let’s add a web component input parameter so that we can get data from outside for the creation of the web component.

Step 12: In the src/app/app.component.ts for the phoenix-wc-wiki-ngx-lt project, we’re going to add an input element called “token.” For this, we have to add the functions ngOnInit and ngOnChanges to handle incoming data:

In the src/app/app.component.ts for the phoenix-wc-wiki-ngx-lt project, we’re going to add an input element called “token.”

Step 13: After generating the build, we can add the new value to the declaration of the web component.

<phoenix-wc-wiki-ngx-lt token="token Value Test"></phoenix-wc-wiki-ngx-lt>

Step 14: Let’s hit refresh and open the browser console:
After generating the build, we can add the new value to the declaration of the web component. <phoenix-wc-wiki-ngx-lt token="token Value Test"></phoenix-wc-wiki-ngx-lt>

 

Using Custom Events to Communicate Data Between Web Components and Container App

What if we need to send data from one web component to another? 

To accomplish this, we’re going to use Custom Events. This communication interface provides us with clean, cross-platform communication between the web components for different technologies.

 

Custom Event Dispatcher

Step 1: In the src/app/app.component.html for the project phoenix-wc-wiki-ngx, let’s create a button with the function sendCustomEvent on click.

<button (click)="sendCustomEvent()">Custom Event</button>

In the src/app/app.component.html for the project phoenix-wc-wiki-ngx, let’s create a button with the function sendCustomEvent on click. <button (click)="sendCustomEvent()">Custom Event</button>

Step 2: In the src/app/app.component.ts, add the function sendCustomEvent with the dispatcher of the custom event.

The name of the custom event {project-name}-ce-{action}

In the src/app/app.component.ts, add the function sendCustomEvent with the dispatcher of the custom event. The name of the custom event {project-name}-ce-{action}

Step 3: Now that we have the dispatcher, we’re going to add the listener to the web component phoenix-wc-wiki-ngx-lt.

 

Custom Event Listener

Step 4: In the src/app/app.component.ts:

• Create a custom event function in charge of handling the data and call from the custom event (to handle de data use event.detail)

customEventListenerFunction(event) {console.log('testfunc - ' , vent.detail);}

• Add the listener to the ngOnInit function to the custom event function

window.addEventListener('phoenix-wc-wiki-ngx-ce-data-sent-test', this.customEventListenerFunction, true);

• Implement the function ngOnDestroy

implements OnInit, OnChanges, OnDestroy {

• Add the remove listener to the ngOnDestroy

ngOnDestroy():void{window.removeEventListener('changeNameToCustomEvent', this.customEventListenerFunction, true);}

Create a custom event function in charge of handling the data and call from the custom event (to handle de data use event.detail). Add the listener to the ngOnInit function to the custom event function. Implement the function ngOnDestroy. Add the remove listener to the ngOnDestroy.

 

After we generate the builds and hit refresh to http://localhost/9080/, we can see in the console, if we hit the button in the first web component, how the phoenix-wc-wiki-ngx-lt-bundle.js executes the function added as a listener.

how the phoenix-wc-wiki-ngx-lt-bundle.js executes the function added as a listener.

 

Lazy Loading Web Components

Step 1: Let’s add @angular-extensions to the project.

npm i --save @angular-extensions/elements

Step 2: Append LazyElementsModule to the imports: [] of your AppModule

Add new schemas: [] property with CUSTOM_ELEMENTS_SCHEMA value to @NgModule decorator of your AppModule

Add @angular-extensions to the project. Append LazyElementsModule to the imports: [] of your AppModule Add new schemas: [] property with CUSTOM_ELEMENTS_SCHEMA .

After this, we can use the *axLazyElement directive to lazy load the web components.

Step 3: Add a variable with the URL of the location of our web component.

elementFUrl = 'assets/elements/phoenix-wc-wiki-ngx';

Or

elementFUrl = 'https://cdn.ourwebhosting.com/1.2.3/elements/phoenix-wc-wiki-ngx';

 

Step 4: In the template .html, add the *axLazyElement directive.

<phoenix-wc-wiki-ngx *axLazyElement="elementFUrl"></phoenix-wc-wiki-ngx>

 

ZoneStrategy

Sometimes the parent application is an Angular app. To avoid ngzone conflicts, we’re going to use ElementZoneStrategyFactory when we instance the web component.

Step 1: Just change the ngDoBootstrap in the app.module.ts:

ngDoBootstrap() {const strategyFactory = new ElementZoneStrategyFactory(AppComponent,this.injector);

const eventsElement = createCustomElement(AppComponent, {injector: his.injector,strategyFactory});
customElements.define('phoenix-wc-wiki-ngx', eventsElement);}

 

To conclude, the micro frontend architecture allows companies to give their dev teams absolute control over their knowledge, the freedom to mix different technologies by taking advantage of the strengths of each framework to solve different problems, and allows for the reuse of web components in multiple applications. However, it is important to keep in mind that the more web components with different technologies you have, the more dev teams you’ll need to maintain the code and deployment if you have CI/CD in your development process. 

I hope this gives you a clear picture of what a micro frontend architecture is, how to use it in Angular, and the reasons why this new way of creating web applications can benefit your dev teams and your business as a whole.

 

New call-to-action

Hetzel Cordoba
Hetzel Cordoba

Hetzel Cordoba is a software engineer who graduated from the University De Los Andes in Bogotá, Colombia. His passion lies in the exploration of multiple fields like machine learning, front/back end, and blockchain, he also enjoys writing poetry.

Related Articles

Ready to be Unstoppable?

Partner with Gorilla Logic, and you can be.