Progressive Web Apps

15-03-2017 - Bram Smulders

Howdy,

Bram Smulders
bramsmulders.com
@bramsmulders
bramsmulders.github.io/slides

Why?

The new mobile environment

  • More users have access to the web
  • They're not always on the best networks
  • Do not always have the best Devices

And I'm not even talking about upcoming markets

PWA's excel in the mobile landscape

  • Efficient use of the disk
  • Efficient use of the network
  • Do not require large installs

The three requirements

HTTPS

  • Secure
  • Trustworthy
  • Higher ranked in search engines

Service worker

  • Lives in the browser
  • Can cache assets
  • Can make cache available offline
  • Can run in the background to finish tasks

Reference the service worker

if ('serviceWorker' in navigator) {
    window.addEventListener('load', function() {
        navigator.serviceWorker.register('/sw.js').then(function(registration) {
            // Registration was successful
            console.log('ServiceWorker registration successful with scope: ', registration.scope);
        }).catch(function(err) {
            // registration failed :(
            console.log('ServiceWorker registration failed: ', err);
        });
    });
}

Define the cache

const cacheName = 'bramsmulders:4.1.3';
const cacheFiles = [
    '/about/',
    '/offline/',
    '/blog/structured-frontend-components/',
    '/blog/how-i-improved-my-workflow-with-smacss-sass/',
    '/blog/finger-friendly-all-the-things/'
];

Install the service worker

self.addEventListener('install', (event) => {
    event.waitUntil(
        caches
            .open(cacheName)
            .then((cache) => {
                // console.log('Opened cache');
                return cache.addAll(cacheFiles);
            })
    );
});

Listen to the network

self.addEventListener('fetch', (event) => {
    event.respondWith(
        caches
            .match(event.request)
            .then((response) => {
                // Grab the response from asset cache
                if (response) {
                    return response;
                }
                return fetch(event.request);
            })
            .catch(() => {
                // Network is offline, return the cached offline page
                return caches.match('/offline/');
            })
    );
});

Update the service worker

self.addEventListener('activate', (event) => {

    const cacheWhitelist = ['bramsmulders:4.1.3'];

    event.waitUntil(
        caches.keys().then((cacheNames) => {
            return Promise.all(
                cacheNames.map((cacheName) => {
                    if (cacheWhitelist.indexOf(cacheName) === -1) {
                        return caches.delete(cacheName);
                    }
                })
            );
        })
    );
});

Web app manifest

manifest.json

{
    "short_name": "Bram Smulders",
    "name": "Bram Smulders; UX and Front-end architecture enthousiast",
    "start_url": "/",
    "background_color": "#ffffff",
    "theme_color": "#fc6471",
    "display": "standalone",
    "icons": [
        {
            "src": "\/android-icon-144x144.png",
            "sizes": "144x144",
            "type": "image\/png",
            "density": "3.0"
        }
    ]
}

Tell the browser about the file

Testing the banner

Did the user install?

window.addEventListener('beforeinstallprompt', function(e) {
    // beforeinstallprompt Event fired

    // e.userChoice will return a Promise.
    e.userChoice.then(function(choiceResult) {

        console.log(choiceResult.outcome);

        if(choiceResult.outcome == 'dismissed') {
            console.log('User cancelled home screen install');
        } else {
            console.log('User added to home screen');
        }
    });
});

Tools of the trade

Lighthouse

  • Open source by google
  • Combines PWA tests with pagespeed tests
  • Gives advice on where and how you can improve

Lighthouse Chrome plugin

Lighthouse CLI

Lighthouse Report - PWA

Lighthouse Report - Best practices

Lighthouse Report - Performance

Demo

Installation prompt

Splashscreen

Opened

Offline

Offline from cache

Usefull links