using Angular Service Worker

Maxim Salnikov

Angular GDE

Automatic

Progressive Web Apps 

How to create an Angular Progressive Web App?

Natively & naturally

Maxim Salnikov

  • Full-Stack Engineer at ForgeRock

  • PWAngelist / trainer

  • LondonPWA and OsloPWA meetups organizer

  • ngVikings conference organizer

After all, what is PWA?

Progressive web apps use modern web APIs along with traditional progressive enhancement strategy to create cross-platform web applications.

These apps work everywhere and provide several features that give them the same user experience advantages as native apps.

Cross-platform?

Browser

Desktop

Mobile

App store?

Dev builds

During last two weeks

UX advantages?

Working offline

Proper app experience

Smarter networking

Staying notified

}

Service Worker

API

Web App Manifest

  • 1300+ developers

  • Major browsers/frameworks/libs reps

+

=

<script />

+

=

Angular Service Worker

NGSW

Generate a new Angular PWA

$ ng new myPWA --mobile
  • Angular CLI < 1.6

  • Angular Service Worker β

Yesterday

Angular Mobile Toolkit

Generate a new Angular PWA

$ ng new myPWA --service-worker
  • Angular CLI 1.6-1.7 

  • Angular Service Worker 5

Today

Generate a new Angular PWA

$ ng new myPWA
  • Angular CLI 6

  • Angular Service Worker 6

  • Web App Manifest

  • @Schematics

Tomorrow

$ ng add @angular/pwa --project=myPWA

Building Angular PWA

$ ng build --prod

ngsw-worker.js

ngsw.json

dist/

Hint #1: Checking the status

https://yourwebsite.com/ngsw/state

NGSW Debug Info:

Driver state: NORMAL ((nominal))
Latest manifest hash: cd4716ff2d3e24f4292010c929ff429d9eeead73
Last update check: 9s215u

=== Version 34c3fd2361735b1330a23c32880640febd059305 ===

Clients: 7eb10c76-d9ed-493a-be12-93f305394a77

=== Version cd4716ff2d3e24f4292010c929ff429d9eeead73 ===

Clients: ee22d69e-37f1-439d-acd3-4f1f366ec8e1

=== Idle Task Queue ===
Last update tick: 4s602u
Last update run: 9s222u
Task queue:


Debug log:

Adding NGSW to the existing app

$ ng set apps.0.serviceWorker=true
$ npm install @angular/service-worker --save

1. Install the package

2. Enable build support

3. Register NGSW for your app

4. Create configuration file

Service worker build support in the CLI

Build

Copy

src/ngsw-config.json

dist/ngsw.json

ngsw-worker.js

dist/

node_modules/@angular...

Can be npm-scripted for legacy Angular CLIs!

Registering NGSW

import { ServiceWorkerModule } from '@angular/service-worker';
import { environment } from '../environments/environment';
...
@NgModule({
  ...
  imports: [
    ...


  ]
})
export class AppModule { }
    ServiceWorkerModule.register('/ngsw-worker.js',
        { enabled: environment.production }),

app.module.ts

NGSW configuration file

src/ngsw-config.json

{
  "index": "/index.html",
  "assetGroups": [...],
  "dataGroups": [...]
}

Working offline

Proper app experience

Smarter networking

Staying notified

App shell

assetGroups

{
    "name": "app",
    "installMode": "prefetch",
    "resources": {...}
}

App shell resources

assetGroups / "app" / resources

"resources": {









}
    "versionedFiles": [
      "/*.bundle.css",
      "/*.bundle.js",
      "/*.chunk.js"
    ],
    "files": [
      "/favicon.ico",
      "/index.html"
    ],

App shell / on-demand

assetGroups

{
    "name": "assets",
    "installMode": "lazy",
    "updateMode": "prefetch",
    "resources": {...}
}

App shell / on-demand

assetGroups / "assets" / resources

"resources": {








}
    "files": [
      "/assets/**"
    ],
    "urls": [
        "https://fonts.googleapis.com/**",
        "https://fonts.gstatic.com/**"
    ]

Runtime caching

dataGroups

{
    "name": "api-freshness",
    "urls": [
      "/api/breakingnews/**"
    ],






}
    "cacheConfig": {
      "strategy": "freshness",
      "maxSize": 10,
      "maxAge": "12h",
      "timeout": "10s"
    }

Runtime caching

dataGroups

{
    "name": "api-performance",
    "urls": [
      "/api/archive/**"
    ],






}
    "cacheConfig": {
      "strategy": "performance",
      "maxSize": 100,
      "maxAge": "365d"
    }

Hint #2: Support API versioning

dataGroups

{
    "version": 1,
    "name": "api-performance",
    "urls": [
      "/api/**"
    ],
    ...
}
{
    "version": 2,
    "name": "api-performance",
    "urls": [
      "/api/**"
    ],
    ...
}

App version updates

v1

v2

v1

v1

v2

Server

Browser

v2

Hint #3: Notify about updates

import { SwUpdate } from '@angular/service-worker';
constructor(private swUpdate: SwUpdate) {}
this.swUpdate.available.subscribe(event => {
  let snackBarRef = this.snackBar
    .open('Newer version of the app is available', 'Refresh');

  snackBarRef.onAction().subscribe(() => {
    window.location.reload()
  })
})

updates.component.ts

Working offline

Proper app experience

Smarter networking

Staying notified

Push notifications

import { SwPush } from '@angular/service-worker';
constructor(private swPush: SwPush) {}
subscribeToPush() {
  this.swPush.requestSubscription({
    serverPublicKey: this.VAPID_PUBLIC_KEY
  })
    .then(pushSubscription => {
      // Pass subscription object to backend
    })
}

push.component.ts

Push notifications / send

{
  "notification": {










  }
}

server-side.js / sendNotification payload

    "title": "Very important notification",
    "body": "Angular Service Worker is cool!",
    "icon": "https://angular.io/assets/logo.png",
    "actions": [
      {
        "action": "gocheck",
        "title": "Go and check"
      }
    ],
    ...

Hint #4: Kill switch

1. Long way

ng set apps.0.serviceWorker=false
ng build --prod
...deploy

2. Short way

rm dist/ngsw.json
...deploy

Hint #4: Kill switch

3. Proper way

cp dist/safety-worker.js dist/ngsw-worker.js
...deploy
self.addEventListener('install', e => { self.skipWaiting(); });

self.addEventListener('activate', e => {
  e.waitUntil(self.clients.claim());
  self.registration.unregister().then(
      () => { console.log('Unregistered old service worker'); });
});

safety-worker.js

Main available features

App Shell

Runtime Caching

Push Notifications

Smart Updates

Angular Service Worker advantages

  • Essential features are config-driven

  • Decoupled updates model

  • Integrity checks

  • Doing things in Angular way

Thank you!

@webmaxru

Maxim Salnikov

Questions?

Automatic Progressive Web Apps using Angular Service Worker

By Maxim Salnikov

Automatic Progressive Web Apps using Angular Service Worker

Progressive Web Apps are the next big thing for the web. They combine the advantages of two platforms: searchability and shareability of the web with capabilities and performance of native mobile. As a result, web developers can use their favourite tools to build installable, re-engageable, connectivity independent apps, that can bring native-like performance and user experience. The Angular Service Worker makes it easy to get started building PWA. It’s developed to automate main routines and provide us with some nice tools to control the progressive app behaviour. During this practical session, we'll have a look at NGSW’s main components, and how they take our web app to the next level. With just some simple updates we’ll get installable, offline-capable, mobile-network-friendly Angular app re-engaging users by push-notifications.

  • 4,670