Before jumping into converting Angular applications into a PWA, Let’s get to know what PWA is.
What makes an app a PWA?
An app can be considered a PWA when it meets the following requirements.
- Works offline
- Responsive to any screen size
There are many other features that can add to it like push notifications, access to sensors, geolocation, etc
Though PWAs have many advantages there are also few limitations like partial iOS support, some features not supported in all browsers, and no access to various device features like NFC, Bluetooth, advanced camera controls, contacts, etc
There are two main components required to turn any web application into a PWA
- Manifest File: It’s a JSON file with information about the web application. For example, the icon to be displayed on the home screen, the short name of the application, etc. Adding the manifest file will make our application installable to a device’s home screen without an app store.
We can convert almost any web app into a PWA by adding the above two components and it means that we can build a PWA rather quickly, in comparison to a native/hybrid app.
Let’s start converting an Angular app into a PWA.
Adding PWA components to the project
Run the below CLI(v6.0+) command in the existing responsive Angular application replacing the <project-name> with your project name available in the angular.json file.
ng add @angular/pwa — project <project-name>
This will make the below updates to the Angular application that are required for PWA.
Registering Service Worker
In app.module.ts, will see the below code being added to register the service worker.
Here the Service worker is registered with the default registration strategy “registerWhenStable” and so the registration will happen only after the app is stable. For example, if we have used recursive functions like setInterval(), the app will never become stable and the Service worker will not get registered on page load. In such cases, we can use the registration strategy “registerImmediately” as below.
There’s also an option to pass an observable, to have it registered whenever we think it’s right.
One more thing to note about Service workers is it only runs over HTTPS to restrict hacking attacks while intercepting network requests. So, ensure the application is running in HTTPS.
Configure Home Screen Icons in Manifest
The manifest file, manifest.webmanifest created by running the angular CLI command will be available in the Project root directory. This file contains the key PWA properties like short_name and/or name, icons, start_url, background_color, etc. We can configure these properties as per our need.
Lets see how we can create icons and configure the icons in the manifest file.
For Chrome browser, it's mandatory to provide a 192x192 pixel icon and a 512x512 pixel icon. If no other icon sizes are provided, Chrome will automatically do the scaling to match the device. If we want to scale our own icons and adjust them for pixel-perfection, we can add icons in other sizes too.
There is a tool available(https://github.com/ezzabuzaid/pwa-icon-generator) to easily generate icons in different sizes and we can use it for generating the icons.
The icons property in the manifest file is an array of image objects and we can use the generated icons in the manifest file as below.
For iOS home screen icon support, we need to add a link tag in index.html with rel=”apple-touch-icon” as below
Offline Support (Optional)
Users expect apps to work regardless of their connection status. Native apps never show a blank page when it’s offline, and a PWA should never show the browser default offline page.
Service workers use the Cache interface to cache the application’s assets to provide offline access. Angular’s service worker cache the whole application (all of the files the browser needs to render this application) as a single unit and all files update together to provide a native app-like experience.
The ngsw-config.json boilerplate configuration created by CLI is set up to cache the required assets to provide offline access. This can be configured as per the need to add/remove assets. Additionally, we can cache data resources that are not configured in ngsw-config.json by default.
We need to add a new field, dataGroups which contains an array of data groups to cache API requests and other data dependencies. Below is an example of a Data group.
There are 2 caching strategies available:
performance returns from the cache and no network requests are made. This improves performance but in exchange even if updated data available the site might be loading old data from the cache. The updated data will be loaded only after the maxAge is reached for the old data.
freshness fetches from the network by default and falls back to the cache only if the network times out.
But in the above example we have emulated the third strategy, staleWhileRevalidate, which returns cached data (if available), but also fetches fresh data from the network in the background for next time. As we have set strategy to freshness it will try to fetch from the network first but we have also set timeout to 0u, thus data is returned immediately from treasureand new response from the network updates the cache for future requests.
Also to be noted, To keep the cached data size under the limit, the browser will start removing the cached data associated with an origin if the cached data size exceeds the browser’s storage limit.
Validate PWA using Lighthouse
With the required PWA components added to our application, we can use Lighthouse, an open-source tool from Google to audit our web app for PWA features. Using this tool we can generate a validation report as below.
Once the app is validated without any errors, check the site in the mobile browser. In Mobile Chrome, upon loading the site, and install banner pops up asking to add this app to the Home screen and it can be tapped to add to the home screen. In other browsers, the Add to Home screen will be available in the browser menu.
That’s it! Our site is on the home screen similar to other native apps and tapping on the home screen icon opens up the site in full screen providing the native app-like experience.
Implement Push Notifications (Optional)
PWAs support push notifications and it is the same as native notifications that we receive on our mobile phones. It is one of the most important features to compete with native apps. Push notifications are pushed from the server to users’ devices, even when the page or application is not running and so this greatly helps in re-engaging the user.
Notifications aren’t directly pushed from the backend server to the user’s browser. Rather, they are pushed from servers chosen by browser development companies to ensure notifications are not very disruptive to the user.
The first step we should do is to uniquely identify our server to the several Browser Push Servers available. To do so we need a VAPID (Voluntary Application Server Identification) key pair. To generate a VAPID key pair we need to install the webpush library and generate the key pair using the below commands.
npm install web-push -g
web-push generate-vapid-keys — json
Here is the sample VAPID key pair generated using the above command
We have the Service Worker already registered, have the VAPID public key and now we can request the user permission for sending Push Notifications. We can add the below function and call it on page load to request for user subscription and get the subscription object.
If the user accepts to allow notifications, we will get the subscription object in the success callback. We have to send this subscription object to our backend server and this has to be stored to send the notifications to the subscribed users. We can use any backend technology and push notification library to store the subscription objects and send the notification to all subscribed users. Below is the sample code to send push notifications using Node Backend and webpush library.
The payload of the message will be sent to the Browser Server and this will forward the message to the user’s browser based on the unique URL of the endpoint in the subscription object. Using the Notifications API, the Service Worker will then show the notification to the user. Hope this helps in getting started with PWA Push notifications.
The PWA features added to the application are in action! Check out the screenshots below
Overall the article covered the basics of PWA and simple steps to add PWA to our existing Angular application with important features like offline support and push notifications.