Serve Content When User is Offline with Service Workers in Angular
There may be times when your users won't have internet access. This means when they attempt to load or reload your app they'll see the dreaded "No internet" page.
It doesn't need to be this way as Progressive Web Applications (PWA) have service workers baked in to solve this exact problem. A service worker acts as a proxy between your application and the network. So if a user requests some content the Service Worker will first see if it has a cache with the content and only if it doesn't a network request will be made to fetch the content.
Thankfully, making your Angular app a PWA can be done via a Angular schematic. Below we'll go through the setup and see what the PWA schematic does and how we know our app is now a PWA and serving content even when a user is offline.
Setup
Let's create out app via the angular CLI.
ng new angular-pwa
Adding PWA support to your Angular app is very simple, just run the schematic below and you are done.
ng add @angular/pwa
This will create and modify a number of files.
The manifest.webmanifest is arguably the most critical here as without it your app will not be recognized as an PWA. It's job is to inform the browser that this app is an PWA and therefore can be installed by users. When a user chooses to install your app you can provide some additional information to improve the installed app experience, e.g. theming, icons and name.
Angular.json is updated to add the manifest.webmanifest to your app assets so it can be discovered when your app is loaded.
The app.module.ts file will be updated to register the Service Worker, as shown below.
So we are registering ngsw-worker.js and defining a registration strategy. We are choosing to register our service worker immediately. The alternate strategies would be to register when our application stabilizes, using registerWhenStable, or register with a delay using registerWithDelay. You may notice there is no ngsw-worker.js file!!! Fret not, the ngsw-worker.js file will be created when your application is built. If you look under your dist/ folder you can view it.
ngsw-config.json is also added to the angular.json file. This file defines how the service worker will cache our content.
An PWA must be run with https enabled for it to work, this is a feature that makes PWAs more secure by default. This means running `ng serve` will not work. So we need to build our app and serve it with an alternative http server.
To do this install npm install http-server if it is not already installed and run ng build --prod && http-server -p 8080 -c-1 dist/angular-pwa. Now we can visit our app running locally http://localhost:8080.
Install Web Application
You should see an install button next to the bookmark button in the browser URL bar (I'm using Chrome).
Click on this and try out installing you application. The install will create a shortcut on your desktop that will allow you to launch you app in future, pretty sweet!!
If the webmanifest shows there is a problem with the service worker registration, try refreshing or restarting your application. Open devtools and look under Application > Manifest and you should see similar to below. This means the application has found the webmanifest and loaded it.
Service Worker
Next up is the service worker. This acts as a proxy between your application and the network. So if a user requests some content the service worker will first see if it has a cache with the content and only if it doesn't a network request will be made to fetch the content.
This means a user who has previously visited your app now has a cache of your chosen content and can access it even when offline. Let's see it in action. In devtools go into offline mode and refresh your app. Hey presto, you're viewing content when offline.
Great, so now lets see what is actually cached and hence will be available even when user is offline.
The ngsw-config.json file is where you specify what and how you'd like your apps content to be handled. By default, you'll see an assetGroups array with an entry for app and one for assets. Each entry can specify it's own install and update strategy.
installMode determines how the content is initially cached and can by defined as prefetch or lazy.
updateMode determines the behavior when a new version of the application is discovered and can also be defined as prefetch or lazy.
To learn more about specific configurations checkout the Angular Service Worker Documentation
That's all for this introduction to the world of PWAs in Angular. There is a lot more functionality on offer and it's relatively simple to get started, from there you can progressively enhance your applications capabilities. So go for it!