Creating Progressive Web Apps using Angular

$whoami

Ahsan Ayaz

Sr. Full Stack Engineer

Check my contributions, throw some stars, follow me.

Feel free to improve (/contribute to) any of my repos

Web Applications' Evolution

  1. Static Web Pages
  2. Interactive pages with Javascript
  3. AJAX
  4. Progressive Web Apps

Progressive Web Applications

Characteristics of PWAs

According to Google, PWAs should be: 

  • Reliable
  • Fast
  • Engaging
  • Easily Accessible

Let's create a simple PWA

Make it Reliable

We'll use Service Workers to make our app more reliable for users

Angular Team ftw

Angular team provides us some really amazing tools to make our apps PWAs. Let's install the tools required by doing :

npm install --save @angular/service-worker @angular/platform-server ng-pwa-tools
# OR
yarn add @angular/service-worker @angular/platform-server ng-pwa-tools --save

Enable Service Workers for our app

Let's update our `angular-cli.json` to enable our service workers. We can manually do it but can be done using this command: 

ng set apps.0.serviceWorker=true

This should generate ngsw-manifest.json in our dist folder from now on, on doing ng build --prod

Let our Service Worker know about the app's routing 

The manifest knows about the assets. Let's make it aware of the app's routing. We'll add the following command to our run.sh

# merge ngsw-manifest and copy to dist
./node_modules/.bin/ngu-sw-manifest --module src/app/app.module.ts \
                --out dist/ngsw-manifest.json

Configure Service Worker for Bookings API (rest calls)

We'll create ngsw-manifest.json inside our app's `src` folder and put the following code there

{
    "dynamic": {
        "group": [
        {
            "name": "booking api",
            "urls": {
            "https://www.googleapis.com/books/": {
                "match": "prefix"
            }
            },
            "cache": {
            "optimizeFor": "performance",
            "maxAgeMs": 3600000,
            "maxEntries": 20,
            "strategy": "lru"
            }
        }
        ]
    }
}

We're optimizing for performance. 

We could also optimize for freshness

Caching External Resources

By default, the service worker does not cache external resources like fonts etc included via CDN

{
    .
    .
    .
    "external": {
        "urls": [
            {"url": "https://fonts.googleapis.com/icon?family=Material+Icons"}
        ]
    }
}

We'll add some more configuration to our ngsw-manifest.json

Make it Faster

We'll use App Shell to enhance our home page experience to users

First of all, change the BrowserModule config

BrowserModule.withServerTransition({appId: 'ng-books'}),

Creating the rendered html via app-shell

node_modules/.bin/ngu-app-shell --module src/app/app.module.ts \
    --out dist/index.html

Make it Engaging

Enable push notifications

Update manifest to enable notifications

{
    .
    .
    .
    "push":{
        "showNotifications" : true
    }
}

Add NgServiceWorker in the app

import { NgServiceWorker, ServiceWorkerModule } from '@angular/service-worker';

Register for push and listen to notifications

constructor(private sw: NgServiceWorker) {
    sw.registerForPush({
        applicationServerKey: '<server-key>'
    }).subscribe(sub => {
        console.log(sub.toJSON());
    })
    
    sw.push.subscribe(notif => {
        console.log(notif);
    })
}

Make it Easily Accessible

Make it installable

First we need to add webmenifest.json in our project in src folder

{
  "name": "Ng Books PWA",
  "short_name": "Ng Books PWA",
  "icons": [
	
  ],
  "theme_color": "#000000",
  "background_color": "#e0e0e0",
  "start_url": "/index.html",
  "display": "standalone",
  "orientation": "portrait"
}

Then we'll create icons for our manifest. 

realfavicongenerator.net is a great site to create favicon for all devices.

Download the icons and paste it inside src/favicon.

We'll then add those android icons inside our manifest.json

{
  "name": "Ng Books PWA",
  "short_name": "Ng Books PWA",
  "icons": [
	{
			"src": "/favicon/android-chrome-36x36.png",
			"sizes": "36x36",
			"type": "image/png",
			"density": 0.75
		},
		{
			"src": "/favicon/android-chrome-48x48.png",
			"sizes": "48x48",
			"type": "image/png",
			"density": 1
		},
		{
			"src": "/favicon/android-chrome-72x72.png",
			"sizes": "72x72",
			"type": "image/png",
			"density": 1.5
		},
		{
			"src": "/favicon/android-chrome-96x96.png",
			"sizes": "96x96",
			"type": "image/png",
			"density": 2
		},
		{
			"src": "/favicon/android-chrome-144x144.png",
			"sizes": "144x144",
			"type": "image/png",
			"density": 3
		},
		{
			"src": "/favicon/android-chrome-192x192.png",
			"sizes": "192x192",
			"type": "image/png",
			"density": 4
		}
  ],
  "theme_color": "#000000",
  "background_color": "#e0e0e0",
  "start_url": "/index.html",
  "display": "standalone",
  "orientation": "portrait"
}

Now, we'll add the manifest file and favicon links for other devices in index.html

<link rel="apple-touch-icon" sizes="180x180" href="favicon/apple-touch-icon.png">
<link rel="icon" type="image/png" sizes="32x32" href="favicon/favicon-32x32.png">
<link rel="icon" type="image/png" sizes="16x16" href="favicon/favicon-16x16.png">
<link rel="mask-icon" href="favicon//safari-pinned-tab.svg" color="#5bbad5">
<link rel="manifest" href="/webmanifest.json">
<meta name="theme-color" content="#ffffff">

The favicon folder we just created doesn't get copied in dist folder right now. Let's do that by adding it in angular-cli.json

 

.
.
"assets": [
    "assets",
    "favicon",     <- like this
    "favicon.ico"
],
.
.

Let's test on iOS

Some good reads/links for you

Thank You!

Ahsan Ayaz

Sr. Full Stack Engineer

Creating PWAs using Angular

By Ahsan Ayaz

Creating PWAs using Angular

The slides are meant to be for talks given at different places and they explain how we can quickly create Progressive Web Apps using Angular (2+). This works for new projects as well as projects you might have already created

  • 1,540
Loading comments...

More from Ahsan Ayaz