<img height="1" width="1" style="display:none" src="https://www.facebook.com/tr?id=1063935717132479&amp;ev=PageView&amp;noscript=1 https://www.facebook.com/tr?id=1063935717132479&amp;ev=PageView&amp;noscript=1 "> Bitovi Blog - UX and UI design, JavaScript and Front-end development

Module Federation and Angular Service Workers (PWA)

Idris Shedu

Leverage service workers to ensure 100% uptime on an application that uses Module Federation

posted in Angular, Performance, Micro Frontend on April 15, 2022 by Idris Shedu


Module Federation and Angular Service Workers (PWA)

Idris Shedu by Idris Shedu

Do you use the Module Federation plugin in your Angular project? If your project dynamically consumes large federated code chunks from a remote container, you risk having downtime in your remote server or having lags when you navigate between routes. If so, you should use Angular service workers to cache and serve your federated code.

Service workers significantly improve user experience and ensure your remote containers are always available to be consumed, even when the remote server is down. In this blog post, we will go over how to set up service workers in your application and we will learn some of the best caching strategies for module federation. Get started with Module Federation in Angular by reading this blog post.

What is an Angular Service Worker?

By definition, the service worker is a script that runs on the browser it acts as a bridge between browsers and the network, intercepts requests made by the document, and can redirect requests to a cache. Service workers perform many other features including Push Notifications and background sync. Learn More.

Angular Service workers satisfy the demand for a Progressive Web Application that performs well on both fast and slow networks connections. According to the Angular documentation, “Angular service workers can completely satisfy the loading of the application without the need for the network” Learn More.

What are the Benefits of Angular Service Workers?

Service workers improve overall application performance in two ways. First, service workers can cache important files needed by the application. Secondly, service workers can pre-fetch data needed on a given page before users navigate to the page. Here are even more benefits:

Amazing Offline Experience:

If configured correctly, Service Workers ensure the loading of an application without the need for a network by caching and providing all the resources the application needs to load, providing users with a well-balanced offline experience.

Push Notification:

Push notifications provide the ability to receive notifications and perform an action based on the notification received, even when the page is not in focus. Angular service workers enable you to subscribe and listen to Web Push Notifications. It also provides you with the SwPush Service, which enables you to perform push notification operations. Learn More.

Caching Remote Containers in Module Federation :

Using Service Workers on an application that implements Module Federation ensures you have a 100% uptime for all your Remote Containers. Meaning, if any of your remotes are down, the Service Worker will serve users a cached version of the Remote Containers which ensures reliability and also improves the user experience.

Reduce Load on Backend Servers:

Service Workers have the ability to cache API requests to an endpoint and then consequently intercept future requests and serve users with cached data. This would ensure a fast response time, due to a significantly reduced load on the backend servers.

The below code snippet shows the caching strategies for an API request



{
"dataGroups": [

{
"name": "userList",
"urls": [
"https://jsonplaceholder.typicode.com/users" // API URL
]
"cacheConfig": {
"maxSize": 1,
"maxAge": "1d",
"timeout": "10s",
"strategy": "performance"
}
}
]
}

How to Add Service Workers to an Angular Application

Implementing Service Workers in an Angular application is straightforward. Setting Angular Service Workers on an application which consumes Federated Code follows the same process.

To get started you’ll need to follow the following steps.

Install Angular Service Workers

To install Service Workers in an existing Angular application, you first need to make the application a Progressive Web App (PWA) by running:

// run this command on your application root 
ng add @angular/pwa

This command will perform the following actions:

  1. Add the @angular/service-worker package to your project

  2. Create ngsw-config.json file, which holds the Service Worker configurations

  3. Update the index.html file to Include a link to add the manifest.webmanifest file

Now your application is set up to use Service Workers. The next step is to configure your caching strategies to support Module Federation and cache remote containers.

Set Up Caching Strategies for Angular Service Workers:

Caching strategy involves determining which files or assets which should be cached to ensure optimal performance of the application.

Service Workers provide a means for caching files so Navigation Requests (requests the document makes when you enter a new URL in the navigation bar) and other API URL requests can be processed regardless of network availability - so while setting up service workers it is important to select the optimal caching strategy for the application.t. Determining the caching strategies depends on how the Angular app is set up.

 
NOTE: If you have lazy-loaded modules, include them in the caching resources files. Here are the caching strategies used in this example project’s ngsw-config.json file:

// ngsw-config.json

{
"$schema": "./node_modules/@angular/service-worker/config/schema.json",
"index": "/index.html",
"assetGroups": [
{
"name": "app",
"installMode": "prefetch",
"updateMode": "lazy",
"resources": {
"files": [
"/favicon.ico",
"/index.html",
"/manifest.webmanifest",
"/*.css",
"/polyfills.f03e3be7738cc50c.js", // polyfills file
"/main.d18cc3f33a88f6d3.js", // main file
"/styles.ee51bfd27c6cefb9.css", // styles
"/915.158cbfc5e9389d92.js", // Lazy Chunk Files
"/154.9276c38543f8e44a.js" // LazyChunk Files
]
}
},
{
"name": "assets",
"installMode": "lazy",
"updateMode": "prefetch",
"resources": {
"files": [
"/assets/**",
"/*.(svg|cur|jpg|jpeg|png|apng|webp|avif|gif|otf|ttf|woff|woff2)"
]
}
}
]
}

 

Adding Caching Strategies for Module Federation:

Configuring caching strategies for remote containers can be a little bit tricky. Making sure you know all the files your remote needs to run correctly will help you determine the caching strategies you will implement. In the example project, when we dynamically load the remote container, Webpack downloads some missing dependencies:

 

 

Now that we know all the dependencies our remote container will need. Caching the individual files might not be the best approach because file names might change when a new build is done on the remote container. Instead, we can set up the caching strategy to cache all the  .js files from the remote URL. Update the `ngsw-config.json`  to include the caching strategies for the federated chunk files:

{

"name": "FederatedChunk",
"installMode": "lazy",
"updateMode": "prefetch",
"resources": {
"urls": [
"https://module-federation-app2.web.app/*.js",
]
}
},

 

Now, let's break down the configuration strategies seen above:

name: Is used to identify a particular asset group. It is combined with the manifestHash to create the name of the cache location for the particular asset group.

installMode: This option is used to determine how the resources are initially cached which is when the application first loads and after the Service Workers is registered. It consists of two modes:

  1. Prefetch: Tells Angular Service Workers to fetch all the resources in the corresponding asset group while initially caching the application.

  2. lazy: Tells Angular Service Workers to only cache files after it is requested which means if the resource is never requested then it will not be cached.

updateMode: Determines how the resources will be cached when there is a new version of the application.

  1. Prefetch: Option tells Angular Service Workers to fetch all the resources in the corresponding asset group as soon as the new version is available.

  2. lazy: Option tells Angular Service Workers not to cache resources immediately and wait until the resources are requested .

resource: Describes the resource to be cached , it consists of two options files and urls .

  1. files: Lists an array of files in the dist folder that you intend to cache.

  2. urls: Lists an array of URLs matched at run time. Angular Service Workers do not create a hash for the files, but rather it is cached using their HTTP headers.

Learn more about Angular Service Workers Configuration Options.

 

Now that we have finished setting up the caching strategies for our application we can now build and run the application using http-server using the following command:

// Build Project
ng build

// Now serve the application
http-server -p 8080 -c-1 dist/app1-home

 

 

Updating Cached Federated Chunk When a New Version is Available:

Yay! You have successfully cached and served federated code with our Service Workers. The next step is to make sure you always serve the freshest version of the data or files to the user. Angular Service Workers provides us with several options to ensure the freshness of data, such as:

Using the SwUpdate Service: The swUpdate service contains the checkForUpdate() function which enables you to check and install new version updates when available. Learn More. Also, implementing the correct caching strategy can help ensure you’re always getting the freshest data whenever the application refreshes.

Hard Refresh : Performing a hard refresh on Angular Service Worker involves totally unregistering the service worker, removing all resources files from the cache, and then reloading the document to serve the freshest version of the application.

Here are the actions performed when you do a hard refresh:

  1. Unregister Service Worker.
  2. Delete the service worker cached files.
  3. Reload the page.

Below is the code snippet:

hardRefresh() {
navigator.serviceWorker
.getRegistration()
.then(
async (registration: ServiceWorkerRegistration | undefined) =>
{
if(!registration) {
return;
}
await registration.unregister().then();
window.location.assign('<location-to-app-home>');
});
}

 

Key Takeaways

There is a huge performance benefit in using Service Workers in web applications. 
The @angular/service-worker package provides an added advantage in leveraging all the benefits of implementing Service Workers.

Micro Frontend applications using Module Federation can use Service Workers to ensure the reliability of their remote apps. Using the correct caching strategies ensures you have 100% uptime on remote containers which is vital when implementing Micro Frontend architecture.

Resources

 

Create better web applications. We’ll help. Let’s work together.