Progressive Web Apps (PWAs) in Angular – Part 2

| By Maina Wycliffe | | | Angular

Subscribe for more content from me

Google Chrome version 70 was released earlier this week. Among other features, it added support Progressive Web Apps (PWAs) on desktops. This give me an idea for this post where we are going to dive a little bit deeper into PWAs. If you are new to PWAs, please check my introduction to PWAs here. We will focus on two things:

  1. How to check for new versions of your PWAs and
  2. Prompting users to install your PWA

Without further ado:

Checking for New Versions

With PWAs, a lot of the static resources are cached on the client device. So, when you deploy a new version of your app, the users don’t see changes instantly like most web apps. It is therefore important to check for updates manually, download them and then prompt the user when there is a new version.

This would could display a button that when the user reloads the app, it reloads with the new version. If you have used some Google Webs Services such as Android Messages, you might have come across this. This allows you to download the newer version on the background, without interfering with the user experience. Once downloaded, it’s a matter of reloading the browser which will load the latest version. This is simple and almost instant, since all assets and resources have been downloaded and cached locally.

How to Check for New Updates

Progressive Web Apps (PWAs) in Angular – Part 2

PWAs uses a Service Worker to cache most of the static resources, therefore you must use a service worker to check for updates. Service Worker provides a service that you can use to communicate between your app and the service worker. The service is called SwUpdate, and is used just like any other service.

To check for new updates, you first need to inject the SwUpdate service into your component or service:

constructor(private swUpdate: SwUpdate) {}

Then, you can check for new updates as follows.

checkForUpdates() {
  this.swUpdate.available.subscribe(event => {
    // prompt the user to reload the app now
    this.updateAvailable = true;
  });
}

The updateAvailable property, just display a button informing the user there is an update. You can also forcefully reload the browser at this point, which loads the new version. You probably don’t want to do this, because it could ruin the User experience.

reload() {
  window.location.reload();
}

Periodically Checking for New Updates

The above method checks for update once and is triggered by a button click (in this case). You don’t really want the user to be manually checking for updates, but you might want to periodically check for new updates.  This can be achieved using the RXJS Interval method which will tell the service worker to check for new updates on interval.

interval(1000 * 60 * 60 * 2).subscribe(() => this.swUpdate.checkForUpdate());

NB: The above method uses RXJS Interval method to periodically check for updates every 2 hours. Time is provided to the interval method in milliseconds by default.

The checkForUpdate is strange though, it returns a promise but doesn’t indicate whether there is an update or not. So, to be safe, don’t reload when the method is resolved successfully. The good thing though is that, if there is an update available, the next time the user reloads the app, they will load the latest version.

Prompting Users to Install PWAs

Let’s get this out of the way first, browsers have the liberty on how to handle PWAs installs. That said, Google Chrome offers developers the ability to control how to handle PWAs installation. I did some research and experimentation and I could not find how to achieve the same in other browsers.

I will update this post as soon as the situation changes.

If you want to prompt users to install your PWA, you need to listen to beforeinstallprompt event. This event is triggered on every page reload, if the user has not installed your app. This works even after the user has uninstalled the application.

window.addEventListener('beforeinstallprompt', event => {
  this.promptUserInstall();
});

For older version of Chrome (Chrome 67 and lower), you need to add preventDefault() to prevent chrome from showing the default install prompt, before users clicks on your custom install button.

event.preventDefault();

Next, you need to show a custom UI that will prompt the user to install the app.

promptUserInstall() {
  // show prompt here
}

And once the user clicks on the install button, you can then trigger Chrome to show Add App dialog.

this.deferedPrompt.userChoice.then(choiceResult => {
  if (choiceResult.outcome === 'accepted') {
    console.log('User accepted to install PWA');
  } else {
    console.log('User chose not to install PWA');
  }

  this.deferedPrompt = null;
});

NB: As of the time of writing this, this doesn’t trigger the install dialog on Chrome for Desktop. I tested it on current, beta and canary versions of Chrome without success. As a work around, you will have to provide instructions to install the PWA on the desktop version of Chrome. Fortunately, it is not hidden very far, and can easily be located on the menu, so a simple Gif would do.

Progressive Web Apps (PWAs) in Angular – Part 2

Final Thoughts

As time passes, more and more browsers will continue offering standardized PWAs APIs. Hopefully, more and more browsers will support the BeforeInstallPromptEvent so that you can customize the prompt install button.

Thank you for getting this far on this post, I will update it as more information continues to get available for different browser support. If you are interested to learn how to  use Service Workers to Optimize performance of your angular PWA here.

Angular 6 – Introduction to Progressive Web Apps

Earlier this week, I wrote a post about optimizing your angular application using lazy loading. In this post, I will focus on Progressive …

Read More
Angular 6 - Angular CLI Workspaces

One of the least talked about features of Angular 6 is Angular CLI Workspaces. Workspaces or Angular CLI Workspaces give angular …

Read More
APP_INITIALIZER – Tapping into Initialization Process in Angular

In this post, we are going to look at how we can use APP_INITIALIZER in Angular. So, what exactly does APP_INITIALIZER do? The best way to …

Read More
A Better Approach to Environment Variables in Angular

Angular provides a default way to configure environment variables, which you can learn more about here. But in a nutshell, you have …

Read More
Creating Reusable Components in Angular

In this post, we are going to look at tips you can use to make your components more reusable. Reusing components allows developers to …

Read More
Angular Material 7 and CDK News and Updates

In this post, we are going to take a closer look at changes we expect on both Angular Material 7 and Content Development Kit(CDK). While …

Read More

Comments