Building a Progressive Web Application with Angular

0
4062

A progressive Web application (PWA) uses modern Web capabilities to deliver an app-like experience to users. These apps meet certain requirements, are deployed to servers, are accessible through URLs, and indexed by search engines.

The key features of a progressive Web app are listed below.

  • Connectivity independent: It is enhanced with service workers to work offline or on low quality networks.
  • Fresh: It is always up-to-date thanks to the service worker update process.
  • Safe: It is served via HTTPS to prevent snooping and to ensure content has not been tampered with.
  • Discoverable: It is identifiable as an ‘application’ thanks to W3C manifests and service worker registration scope, allowing search engines to find them.
  • Installable: It allows users to ‘keep’ the apps they find most useful on their home screen without the hassle of an app store.

There is a lot here, but it boils down to a few key points.

Offline support: Apps should be able to work offline, whether it is displaying a proper ‘offline’ message or caching app data for display purposes.

Web app manifest: An app manifest file should describe the resources the app needs. This includes the app’s displayed name, icons, as well as splash screen.

Service worker: The service worker provides a programmatic way to cache app resources and API responses.

Why PWAs are hot in the Web app space
On the one hand, we have native apps that are undoubtedly fast and efficient in most cases. On the other hand, there are websites that are somewhat slow and with sketchy connectivity issues, and these only get worse.

The Accelerated Mobile Pages Project (AMP) spearheaded by Twitter and Google was launched in 2016 to solve these slow connection issues. PWAs work flawlessly in all the possible scenarios. With a good connection, there is never a problem. The problem is when there is no or a slow connection and we are greeted with an error page.

Clearly, this can become most annoying if we have a slow connection. The page will seem to be loading, yet all we see is a blank screen. We just wait, wait and wait but the page never seems to load. This is where a PWA comes to our rescue. The best part about it is that you get the best user experience possible on a slow connection, or even with no connectivity.

Things to consider while building a PWA
There are two major things to consider while building a progressive Web application.

App manifest: This is a JSON file that defines an app icon, how to launch the app (standalone, fullscreen, in the browser, etc) and provides any other related information. It’s located in the root of the app. A link to this file is required on each page that has to be rendered. It is added in the head section of the HTML page:

<link rel="manifest" href="/manifest.json">

Service worker: This is where most of the magic happens. It’s nothing but JavaScript code that acts like a programmable proxy solely responsible for intercepting and responding to network requests. Since it acts as a proxy and can easily be programmed, the application must be served over HTTPS to keep the data secure.

Service worker caches the actual response, including all HTTP headers, rather than just the response data. With this, the application can simply make network requests, and process the response without any specific code to handle the cache.

Tools needed to build a PWA
There is no need to build a PWA from scratch or to convert an existing Web app to a PWA, other than adding a manifest file and service worker configuration. For a basic JavaScript Web application, the details are shown here. We will build an application using the Angular framework and then convert that application into a PWA.

Building a PWA using Angular
In this section we will look at some code examples of how to convert a Web application into a PWA using the very popular Angular framework. There are a few pre-requisites, however.

1. A basic understanding of Angular, Components and Angular schematics is needed. A quick refresher can be found at https://codelabs.developers.google.com/codelabs/your-first-pwapp/#0.
2. Angular CLI should be installed on the system in order to run it locally.
3. An HTTP server should be installed on the system to run it locally.
Create a new Angular project using the following code:

ng new ang-angular-pwa-seed

Now go inside the ang-angular-pwa-seed directory and run the following command to build the project:

ng build --prod

Once the project is built, run the following command to invoke the compiled and minified Angular application:

http-server -p 8080 -c-1 dist/ang-angular-pwa-seed

This will run an HTTP server listening on port 8080 at http://127.0.0.1:8080/.

Now, if we run the app in the offline mode, we see the error page. To go offline, right-click on the mouse and click Inspect. Then go to the Application tab and under Service Workers select the Offline checkbox.
This will run a bare minimum Angular application without added support for the PWA. Now that we have a basic Angular application setup, we can work on adding the PWA support. To do so, we need to add @angular/pwa to the Angular application. Install @angular/pwa using the command given below:

ng add @angular/pwa

The above commands will do the following:
1. Add the @angular/service-worker package to your project.
2. Enable the service worker build support in the CLI.
3. Import and register the service worker in the app module.
4. Update the index.html file:

  • Include a link to add the manifest.json file.
  • Add meta tags for the theme colour.

5. Install icon files to support the installed PWA.
6. Create the service worker configuration file called ngsw-config.json.
ngsw-config.json contains the configurations to cache the static assets of the Web application. The contents of the ngsw-config.json are shown below:

{
"$schema": "./node_modules/@angular/service-worker/config/schema.json",
"index": "/index.html",
"assetGroups": [
{
"name": "app",
"installMode": "prefetch",
"resources": {
"files": [
"/favicon.ico",
"/index.html",
"/manifest.webmanifest",
"/*.css",
"/*.js"
]
}
},
{
"name": "assets",
"installMode": "lazy",
"updateMode": "prefetch",
"resources": {
"files": [
"/assets/**",
"/*.(eot|svg|cur|jpg|png|webp|gif|otf|ttf|woff|woff2|ani)"
]
}
}
]
}
Now, run the following command to build the project:

ng build --prod

Once the project is built, run the following command to invoke the compiled and minified Angular application:

http-server -p 8080 -c-1 dist/ang-angular-pwa-seed

This will run an HTTP server listening on port 8080 at http://127.0.0.1:8080/.

We will try to render the application in the offline mode.

Since the application now has PWA support, it will continue to render even if we go offline, since the assets have been cached by the service worker running behind the scenes.
Up to this point we have only learned about how to cache the static assets of the Web application. We haven’t integrated any REST API with the application, and made the necessary changes to cache the API response.

Let’s integrate a REST API with the Angular application and modify ngsw-config.json to cache the API response.

To create any kind of connection to the outside world (REST APIs) we use a construct defined in the Angular domain, called a service.

To create a service in the app, we run the following command:

ng g service dataService

This will generate a service file named data-service.service.ts, and a test file, which contains the code needed to interact with the REST API. For our example application, we used a service to return Lorem Ipsum text. Contents of the data-service.service.ts file are shown in the code snippet below:

import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';

@Injectable({
providedIn: 'root'
})
export class DataServiceService {

constructor(private http:HttpClient) { }

getRandomData(){
return this.http.get('http://www.randomtext.me/api/');
}
}

We also update the ngsw-config.json to add the instruction to cache the API response. The pdated ngsw-config.json is given below:

{
"$schema": "./node_modules/@angular/service-worker/config/schema.json",
"index": "/index.html",
"dataGroups": [
{
"name": "api-performance",
"urls": ["/assets/i18n/**", "/api/**"],
"cacheConfig": {
"strategy": "performance",
"maxSize": 100,
"maxAge": "3d"
}
},
{
"name": "api-freshness",
"urls": ["http://www.randomtext.me/api/"],
"cacheConfig": {
"strategy": "freshness",
"maxSize": 100,
"maxAge": "3d",
"timeout": "10s"
}
}
],
"assetGroups": [
{
"name": "app",
"installMode": "prefetch",
"resources": {
"files": [
"/favicon.ico",
"/index.html",
"/manifest.webmanifest",
"/*.css",
"/*.js"
]
}
},
{
"name": "assets",
"installMode": "lazy",
"updateMode": "prefetch",
"resources": {
"files": [
"/assets/**",
"/*.(eot|svg|cur|jpg|png|webp|gif|otf|ttf|woff|woff2|ani)"

]
}
}
]
}

Now we build the application again using ng build—prod and run it using http-server -p 8080 -c-1 dist/ang-angular-pwa-seed.

Thus we first see the output without going offline.

Next, we toggle the offline radio button and see if the application still works.
And that is it. We have successfully converted an Angular application to a PWA. Web application. All the code that we have shown here can be found on the GitHub repo ang-angular-pwa-seed.

PWAs are the future — where you write your native-like applications using JavaScript, without having to go through difficult build steps and frustrating app stores. With nearly full access to a device’s native functionality, PWAs are bound to take over from native applications and become the No.1 way of creating incredible experiences on all devices.

LEAVE A REPLY

Please enter your comment!
Please enter your name here