One PWA Solution

Maxim Salnikov

@webmaxru

Many Frameworks

How to build a framework-agnostic PWA?

Using the power of your favorite framework

Maxim Salnikov

  • Google Developer Expert, Microsoft MVP

  • PWA London, PWA Oslo meetups organizer, PWA Slack admin

  • Mobile Era, ngVikings conferences founder

Products from the future

Full-Stack Engineer at ForgeRock

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

Flagged

OS

#YearOfPWA

What do frameworks give us?

=

+

Application Shell

Web App Manifest

The most popular frameworks

React

SW library

Out-of-the-box

Configuring

Extending

sw-precache

Web App Manifest

App Shell

create-react-app my-react-pwa

BREAKING NEWS

 

 

 

Angular

SW library

Out-of-the-box

Configuring

Extending

Angular

Service Worker

Web App Manifest

App Shell

Runtime Caching

Push Notifications

Update Flow

$ ng add @angular/pwa

Vue.js

SW library

Out-of-the-box

Configuring

Extending

Workbox

Web App Manifest

App Shell

Runtime Caching

$ vue add @vue/pwa

Built-in PWA support

Pros

Cons

  • Seamless integration

  • Easy to start

  • Limited configuration options

  • Difficult to extend

  • Challenging to add to the existing app

How many frameworks do we use

Requirements

  • Automation of the main service worker tasks

  • Full control and flexibility

  • Framework-agnostic

  • Framework integration

  • CI/CD-friendly

Let's build an App shell

My App

  • Pick only the files we need

  • Create the list of files and their hashes

  • 1st load: put these files into the Cache

  • Next loads: serve them from the Cache

  • Put the updated files (if any) into the Cache using the hash to find them *

  • On the n+1 load - serve the updated  files

The app was updated.

Refresh?

1

2

3

  • Application shell

  • Runtime caching

  • Replaying failed network requests

  • Offline Google Analytics

  • Broadcasting updates

Still our own service worker!

Working modes

  • Workbox CLI

  • Webpack plugin

  • Node module

# Installing the Workbox Node module
$ npm install workbox-build --save-dev

Build script

// We will use injectManifest mode
const {injectManifest} = require('workbox-build')

// Sample configuration with the basic options
var workboxConfig = {...}

// Calling the method and output the result
injectManifest(workboxConfig).then(({count, size}) => {
    console.log(`Generated ${workboxConfig.swDest},
    which will precache ${count} files, ${size} bytes.`)
})

workbox-build-inject.js

App shell file list

[
  {
    "url": "index.html",
    "revision": "34c45cdf166d266929f6b532a8e3869e"
  },
  {
    "url": "favicon.ico",
    "revision": "b9aa7c338693424aae99599bec875b5f"
  },
  ...
]

Build script configuration

// Sample configuration with the basic options
var workboxConfig = {
  globDirectory: 'dist/angular-pwa/',
  globPatterns: [
    '**/*.{txt,png,ico,html,js,json,css}'
  ],
  swSrc: 'src/service-worker.js',
  swDest: 'dist/angular-pwa/service-worker.js'
}

workbox-build-inject.js

Source service worker

// Importing Workbox itself from Google CDN
importScripts('https://googleapis.com/workbox-sw.js');

// Precaching and setting up the routing
workbox.precaching.precacheAndRoute([])

src/service-worker.js

1

2

Build flow integration

{
  "scripts": {
    "build-prod": "ng build --prod &&
                   node workbox-build-inject.js"
  }
}

package.json

App build files

App shell file list

Service worker file

Via hashes

Via injection

Service worker can do more!

// App shell
workbox.precaching.precacheAndRoute([])

// Runtime caching
workbox.routing.registerRoute(
  /(http[s]?:\/\/)?([^\/\s]+\/)api/,
  workbox.strategies.networkFirst()
)

// Push notifications
self.addEventListener('push', (event) => {...})

src/service-worker.js

if ('serviceWorker' in navigator) {
    navigator.serviceWorker
        .register('/service-worker.js')
}

Service worker registration

Requirements

  • Feature detection

  • Registration after app fully loaded and UI rendered

  • Hook into service worker update event

There is a new version of the app is available. Click here to refresh.

  • Was the service worker updated?

  • Was the app itself updated?

register-service-worker

import { register } from 'register-service-worker'

platformBrowserDynamic().bootstrapModule(AppModule)
  .then( () => {
      register('/service-worker.js')
  })

main.ts

$ npm install register-service-worker --save

Catch update event

register('/service-worker.js', {







})

3

    updated (registration) {
        if (confirm(`New content is available!
                     Click OK to refresh`)) {
            window.location.reload();
        }
    }

Tips'n'tricks

  • Trust every resource you want to cache

  • Be careful with the caching resources from the other origins

  • For your service worker file set the no-cache header on the server

Cache-Control: max-age=0

Kill switch

self.addEventListener('install', (e) => {
  self.skipWaiting();
});

self.addEventListener('activate', (e) => {
  self.registration.unregister()
    .then(() => {
      return self.clients.matchAll();
    })
    .then((clients) => {
      clients.forEach((client) => client.navigate(client.url));
    });
});
  • 1700+ developers

  • Major browsers/frameworks/libs reps

Thank you!

Maxim Salnikov

@webmaxru

Questions?

Many frameworks - one PWA solution

By Maxim Salnikov

Many frameworks - one PWA solution

There is no doubt that 2018 is the year when Progressive Web Apps will get the really broad adoption and recognition by all the involved parties: browser vendors (finally, all the major ones), developers, users. How does PWA concept play with YOUR favorite framework? React, Angular, Vue, #FrameworkOfTheWeek? In my technical session we’ll check what major frameworks creators prepared for us regarding scaffolding / adding PWA features (spoiler: only basic features), and switch to Workbox. We’ll see that Workbox is a library providing many sophisticated service worker features in a simple, developer-friendly form. Also, we’ll talk about another advantage of Workbox - the flexibility: you build your own service worker and automate some tasks using this library. As the outcome, you’ll be ready to make a production-ready PWA from the app built on any framework.

  • 1,505