Your Angular app as Progressive Web App

Arjen Brandenburgh
Mar 22 · 9 min read

A Progressive Web App (or PWA) is a web application that provides a set of capabilities to give web sites an app-like experience. Personally, I always feel too many websites create native apps that provide next to no (or even less) additional functionality to their website except being able to have a shortcut. This is where PWAs can play a crucial role. Since Chrome 72 for Android, the Trusted Web Activity feature was shipped, meaning PWAs can be distributed in the Google Play Store, showing that this is an important development.

When building websites, developers have to face several challenges. Internet speed is not as fast everywhere in the world as you may be used to yourself. A website should be performant, so a user doesn’t have to wait when interacting with the website. It also turns out that users don’t often install native apps, simply because the threshold is too high. These challenges are all addressed with a PWA.

PWAs are fast because the app is installed, either through a manual install or through the service worker on the device. Data is cached and we can update the app when there are new changes. PWA’s behave like native apps, which means they can give more seamless and integrated experiences while also providing the benefits of native apps like push notifications. Because of the caching strategies they can paint a picture on a user’s screen when there’s no network. This makes them more reliable.

There are plenty of articles showing how to start a new Angular PWA application, so we’ll focus on upgrading an existing application. For this we’ll be using AngularCLI and Angular 7, since those are all the tools we need. The assumption is that you as reader already have a decent idea about what a service worker is.


Doing the preparations

We’re going to add @angular/pwa to our bundle through AngularCLI which does the following:

  1. Adds the @angular/service-worker package to your project.
  2. Enables service worker build support in the CLI.
  3. Imports and registers the service worker in the app module.
  4. Updates the index.html file to include a link to the manifest.json file and adds the meta tags for theme-color. Change this theme color manually to a color that fits with your app.
  5. Installs icon files to support the installed PWA.
  6. Creates the service worker configuration file called ngsw-config.json, which specifies the caching behaviours and other settings.

Use this in your project folder:

As of writing (Angular 7.2.9 and @angular/pwa 0.13.6) we also need to do a little workaround in main.ts to properly register the service worker. (Angular issue #8779)

Both this above snippet and the changes made in app.module.ts create a reference to the ngsw-worker.js file that you do not see in your project. Don’t worry! The Angular-CLI build will create this for you when you build your app.

Structure of the PWA

Manifest.json

For a PWA to run, we need several extra files. First, we need a manifest.json, which is the web app manifest: a simple JSON file that tells the browser about your web application and how it should behave when “installed” on the user’s mobile device or desktop.

Notable attributes in this manifest are name, short_name, description, theme_color, and background_color. Make sure these are properly entered. The short_name is used as name of your application when added to a home screen, so make sure to add it.

ngsw-config.json

The above steps also generated a ngsw-config.json file, which contains the configuration on how the Angular build process will create your service worker. We will discuss the most important settings in-depth later.

Icons

The icons are more important than you think, so make sure you create them in the proposed sizes. If you’re practical, you can use one of the many online fav-icon generators available. Make sure icons of 192 x 192 pixels and 512 x 512 pixels exist, since these are used by Android to display the “Add to Home Screen” install prompt and used by the Microsoft Store to automatically index and package your app.

If you look in the manifest.json, you’ll see a node icons. Take note of the sizes there that are automatically generated. My advice is that you make sure you have suitable icons for all these sizes.

Unfortunately, Apple’s iOS is still somewhat lagging behind on PWA support. To make sure your app also has an icon on iOS devices, add these lines to your index.html’s head-tag. Make sure the referenced files exist in their respective sizes.


ngsw-config.json

As stated earlier, the ngsw-config.json contains the settings on how the Angular-CLI build process will create your service worker. The default config will basically consist of an index attribute, usually pointing to your index.html, and the assetGroups. With this last attribute you can specify which files will utilise a certain install or update strategy.

Install Strategy

This strategy is to tell the application how it should install the app on the user’s device. By default, the ngsw-worker.js has set the install strategy (installMode) to prefetch, meaning all files specified will be fetched while it’s caching the current version of the app. This is bandwidth-intensive but ensures resources are available whenever they’re requested, even if the browser is currently offline.

The alternative strategy is lazy, which means that resources will only be installed on demand. Usually this strategy will only be used for caching the assets as described next!

Caching Assets

Your assets are configured by default as assetsGroup assets. Again we have the prefetch and lazy strategies available.

Notice that the installMode is set to lazy while the updateMode is set to prefetch, meaning that assets will be loaded on demand, but if an assets has already been cached it will be pro-actively updated. If you want to add assets from external servers or CDNs (like Google fonts), amend the resources like this:

Data Groups

Data Groups are different than assets in the sense that they are not packaged with the version of your app. They could, for example, come from an API. They can be cached with two different strategies: freshness and performance.

The freshness strategy is useful for resources that change frequently and you don’t want to show outdated data for. This strategy will always try to get a new version of the resource before falling back to the cache.

This snippet will get data from the /user endpoint and will be cached for at most 1 hour, a maximum of 5 responses and a timeout of 3 seconds. After this it will fallback to the cache.

The performance strategy, the default strategy, is more useful for resources that don’t change a lot. It will always show the cached version of a resource if available, but this can obviously lead to staleness of the response.


Test drive!

Now when you would launch your application with ng serve, and you check your Application tab in DevTools, you may notice that no service worker has been registered. The Angular-CLI serve function does not support service workers, which is why the service worker does not show up.

We’re going to do an, in my opinion, annoying workaround by doing a production build and serving that independently.

I personally like to set the port of this server to 4200, because when I type an “l” in my url bar, “http://localhost:4200” is the first suggestion that shows up and keeps it in line with ng serve.

Now when we visit localhost:4200, and check our Application tab in DevTools. If you see this, then the service worker has successfully registered.

When you look at your Network tab and refresh (not a hard refresh) you can see the difference in requests. Left you see that the size column indicates how large the downloaded bundle was, and right you see it was loaded from the service worker instead.

However, if you view this on mobile, you will not see an “Add to home screen” prompt from Android. Those will only be brought up over HTTPS connection, so keep that in mind when you’re testing your application in the wild.

The full example

You can find a very simple implementation at https://github.com/arjenbrandenburgh/medium-pwa-example. There’s a separate commit turning the application into a PWA, so you have a clear overview what’s changed.


More functionality

We have our service worker running, files are being prefetched and services are being cached. People can install our app through the “Add to Home screen” prompt and can interact with the application like a native app. While this already sounds like a huge step forward, we have so many more possibilities.

In this article I will not discuss or show how we can extend these functionalities, but rather inform you on what’s possible and available. Read my article about SwPush and SwUpdate for a more in-depth explanation.

SwUpdate: Notify your users on updates

You can leverage the @angular/service-worker SwUpdate to trigger update checks and force updates. For example, when your users are using the app or website and you just deployed a new version, you can trigger a modal or toaster informing the users about this update and ask them to reload to always have the newest experience.

SwPush: Notifications to interact

With the @angular/service-worker SwPush we can subscribe and listen to push notifications from the Service Worker. For this we also need a server to actually send these notifications obviously.


Summary

In this article we have discussed the steps we need to take to upgrade our current application to a PWA. We have seen that with a few simple steps, we can leverage Angular and the Angular-CLI to generate a powerful service worker to give your users a more smooth experience of your website, while still enjoying the benefits of a native app.

Looking for a job in Amsterdam?

I work for Sytac as a Senior Front-end developer and we are looking for medior/senior developers that specialise in Angular, React, Java or Scala. Sytac is a very ambitious consultancy company in the Netherlands that works for a lot of renowned companies in banking, airline, government and retail sectors. You can think of companies like ING, KLM, Deloitte, Ahold Delhaize, ABN AMRO, Flora holland and many more.

From a personal opinion Sytac really sets itself apart with their client portfolio, but also with how they take care of their employees. They do really care about the wellbeing of their employees. Apart from a good salary (50K-75k), you will notice this in regular meetings with the consultant managers but also by the amount of events they organise and all the other perks they offer to keep all employees happy.

If you think you have what it takes to work with the best, send me an email on arjen.brandenburgh@sytac.io and I’ll be happy to tell you more.

Dev Jam

DevJam is a community that aims to enable software professionals to explore new technologies and to stay on top of every thing development.

Arjen Brandenburgh

Written by

Senior Front-end Developer from the Netherlands @ Sytac

Dev Jam

Dev Jam

DevJam is a community that aims to enable software professionals to explore new technologies and to stay on top of every thing development.