Progressive Web Apps

What has the web ever done for us?

Gareth Jones - @nomiddlename

The Plan

  1. Native apps are awesome!
  2. Native apps suck!
  3. What can we do? (SPOILER: PWAs)
  4. How do we do it?
  5. Browsers: Oh, FFS (SPOILER: Google)
  6. The summary for the people who fell asleep

Native apps are awesome!

Performance

Time to first interaction

The average load time for mobile sites is 19 seconds over 3G.
53% of mobile site visits are abandoned if pages take longer than 3 seconds to load.
Doubleclick Report

Repeat customers

Home screen

Push notifications

Up yours, WWW.

Native apps suck!

Most people don't install apps

http://qz.com/253618

People aren't looking for apps

App stores

Barriers

Every step between your users and installing your app loses you 20% of them.

Gabor Cselle

Things to do in Canberra

Go on, go on, go on.

What has the web ever done for us?

Nothing

Well, there's links

...and searching

...and easy distribution

But apart from that?

Nothing.

In summary

  1. Nobody will find your app.
  2. Nobody will install your app.
  3. Nobody will use your app.
  4. You will die penniless and alone.

If only there was another way?

Surprise: Progressive Web Apps!

PWAs

Web Apps

Progressive

Time to first interaction

Service Workers!

Getting onto the home screen

Manifests!

SpammingIncreasing Customer Engagement

Push notifications!

https://nomiddlename.github.io/pow/ - demo site

Service Workers

image/svg+xml Browser Browser The Internet The Internet Service Worker Service Worker Cache Cache

1. HTTPS only (localhost counts as secure)

2. Let the browser know about the service worker.


// this is in your main javascript
if ('serviceWorker' in navigator) {
  navigator.serviceWorker.register('/sw.js')
    .then(() => {
      console.log("Service worker registered!");
  });
}
						

3. The browser installs the service worker


//in your service worker - sw.js
self.addEventListener('install', function(e) {
  e.waitUntil(
    caches.open(cacheName).then((cache) => {
      return cache.addAll(filesToCache);
    })
  )
});


var cacheName = 'pow-v30';
var filesToCache = [
  "bower_components/jquery/dist/jquery.min.js",
  //other css, etc.
  ...
  "js/index.js",
  "data/speakers.json",
  "speakers.html",
  ...
];

4. The browser triggers an activate event


//in your service-worker - sw.js
self.addEventListener('activate', function(e) {
  e.waitUntil(
    caches.keys().then(keys => {
      // delete any old caches
      ...
    })
  )
});

5. Now we can intercept requests


//in your service worker - sw.js
self.addEventListener('fetch', function(e) {
  e.respondWith(
    caches.open(cacheName).then(cache => {
      return cache.match(e.request).then(response => {
        return response || fetch(e.request);
      });
    })
  )
});

6. Serve our app skeleton from the cache

Don't use my dodgy code.

sw-precache (https://github.com/GoogleChrome/sw-precache)

sw-toolbox (https://googlechrome.github.io/sw-toolbox/)

Manifests

Makes your app installable.


							
						

{
  "short_name": "POW! 2016",
  "start_url": "index.html",
  "display": "standalone",
  "icons": [{
      "src": "images/logo.png",
      "sizes": "192x192",
      "type": "image/png"
    }]
}
						

When do you get to install?

  • HTTPS + Service Worker
  • Manifest with "short_name", "start_url", and an icon
  • User visits at least twice, with at least 5 mins between

Annoying?

beforeinstallprompt event

Push notifications

1. Ask for permission

image/svg+xml ratemyduck.com ratemyduck.com Browser Browser User User Browser Browser Push Service Push Service ratemyduck.com ratemyduck.com Server Server

//in your main javascript
navigator.serviceWorker.ready.then(reg => {
  Notification.requestPermission().then(() => {
    reg.pushManager.subscribe({
      userVisibleOnly: true
    }).then(sub => {
      // PushSubscription
    })
  })
})

2. Send a message

image/svg+xml Server Server Push Service Push Service Browser Browser Service Worker Service Worker User User

//server-side code
const push = require('web-push');
push.sendNotification(
  'https://updates.push.services.mozilla....',
  { userPublicKey: '...',
    userAuth: '...',
    payload: '...' }
).then(() => {
  console.log('Message sent.');
});

3. Receive the message


//meanwhile, back in our service worker
self.addEventListener('push', function(e) {
  e.waitUntil(
    self.registration.showNotification(
      "Schedule change",
      { body: e.body.json().message, icon: '...' }
    )
  )
});

Complications

Up yours, native apps!

Browsers: Oh, FFS

Browser support

Android - two thumbs up

  • Service-workers ✓
  • Manifest ✓
  • Push notifications ✓

iOS

  • Service-workers ✗
  • Manifest ✗
  • Push notifications ✗

TL;DR

PWAs bring some benefits of native apps

  • Time to first interaction - Service Workers!
  • Install to home screen - Manifests!
  • User engagement - Push Notifications!

But they don't work on iOS (yet)

Homework

Who was that masked man?

Gareth Jones
@nomiddlename
https://nomiddlename.github.io/yow-connected-2016/