using Angular Service Worker

Maxim Salnikov

Angular GDE

Automatic

Progressive Web Apps 

How to create an Angular Progressive Web App?

Natively

Maxim Salnikov

  • Full-stack engineer at ForgeRock

  • Google Developer Expert in Angular

  • PWA evangelist / trainer

  • Dev communities organizer

It's all about community

ngVikings 2018

March 1-2, Helsinki

ngCommunity

8 Nov, 13:20, "Mars"

Angular Oslo

22 events / 2 hackathons

Progressive Web App

... attempts to combine features offered by most modern browsers with the benefits of mobile experience

... web apps that use the latest web technologies.

10 characteristics

  • Progressive

  • Discoverable

  • Linkable

  • App-like

  • Responsive

  • Connectivity-independent

  • Re-engageable

  • Installable

  • Fresh

  • Safe

Service worker

  • Make some features of the web app function offline

  • Improve online performance by reducing network requests

Service Worker API

  • Receiving push events and displaying notifications

  • Clients (tabs) messaging

  • ...

Not only networking

Logically

Physically

JS

-file

App

Service worker

In Development

Behind the flag

Frameworks

  • create-react-app

  • preact-cli

  • polymer-cli

  • vue-cli

Angular Service Worker

Wait a sec!

  • 800+ developers

  • Major browsers/frameworks/libs reps

Generate a new Angular PWA

$ ng new myProgressiveApp --service-worker

Starting from Angular CLI 1.6

$ ng build --prod

ngsw-worker.js

ngsw.json

dist/

Adding NGSW to the existing app

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

1. Install the package

4. Enable build support

2. Register NGSW for your app

3. Create configuration file

Registering NGSW

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


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

app.module.ts

NGSW configuration file

src/ngsw-config.json

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

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"
    }

Manual build support for Angular CLI 1.5

"ngsw-config": "node_modules/.bin/ngsw-config dist src/ngsw-config.json"

1. Generate a manifest file using ngsw-config tool

2. Copy ngsw-worker.js to the dist folder

3. Run a production build

"ngsw-copy": "cp node_modules/@angular/service-worker/ngsw-worker.js dist/"
"build-ngsw": "ng build --prod && npm run ngsw-config && npm run ngsw-copy"

packages.json / scripts

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"
      }
    ],
    ...

App version updates

v1

v2

v1

v1

v2

Server

Browser

v2

Check for 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

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

On the roadmap

  • Integration with server-side rendering flow

  • Better debugging support

  • Make Angular app progressive by default

  • Documentation!

Thank you!

@webmaxru

Maxim Salnikov

Questions?

Made with Slides.com