Progressive Web Apps (PWAs) in Angular – Part 2

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.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.