$30 off During Our Annual Pro Sale. View Details »

Offline Web Apps (Service Workers)

Offline Web Apps (Service Workers)

Erik Hellman

August 03, 2017
Tweet

More Decks by Erik Hellman

Other Decks in Programming

Transcript

  1. Offline Web Apps

    View Slide

  2. View Slide

  3. View Slide

  4. Lie-fi

    View Slide

  5. of users abandon sites that take
    longer than 3 seconds to load
    53%

    View Slide

  6. 60%
    of world-wide mobile
    connections are 2G

    View Slide

  7. Service Workers

    View Slide

  8. Service Workers are a client-side proxy
    Service worker
    (written in Javascript)
    Cache
    Web server

    View Slide

  9. Service Worker Lifecycle
    • Adds app-like lifecycle to a
    page
    • Wakes up only when the OS
    says
    • Only responds to system
    events
    Activated Error
    Idle
    Active Terminated
    Install
    Register

    View Slide

  10. • Adds app-like lifecycle to a
    page
    • Wakes up only when the OS
    says
    • Only responds to system
    events
    Activated Error
    Idle
    Active Terminated
    Install
    Register
    Service Worker Lifecycle

    View Slide

  11. Service Worker Lifecycle
    • Adds app-like lifecycle to a
    page
    • Wakes up only when the OS
    says
    • Only responds to system
    events
    Activated Error
    Idle
    Active Terminated
    Install
    Register

    View Slide

  12. Service Worker
    is for the SECOND load.

    View Slide

  13. Implementing a Simple Service Worker

    View Slide

  14. Register the Service Worker
    Activated Error
    Idle
    Active Terminated
    Install
    Register

    View Slide

  15. Register the Service Worker
    if ('serviceWorker' in navigator) {
    navigator.serviceWorker.register('/service-worker.js')
    .then(function(reg) {
    console.log('Service Worker Registered', reg);
    })
    .catch(function(err) {
    console.log('Error registering Service Worker', err);
    });
    }

    View Slide

  16. Register the Service Worker
    if ('serviceWorker' in navigator) {
    navigator.serviceWorker.register('/service-worker.js')
    .then(function(reg) {
    console.log('Service Worker Registered', reg);
    })
    .catch(function(err) {
    console.log('Error registering Service Worker', err);
    });
    }

    View Slide

  17. Add an install Event Handler
    Activated Error
    Idle
    Active Terminated
    Install
    Register

    View Slide

  18. Add an install Event Handler
    self.addEventListener('install', function(event) {
    return self.skipWaiting();
    });

    View Slide

  19. Pre-fetch the App Resources
    Activated Error
    Idle
    Active Terminated
    Install
    Register

    View Slide

  20. Pre-fetch the App Resources
    var cacheName = 'app-shell-cache-v1';
    var filesToCache = ['/', '/index.html', ...];
    self.addEventListener('install', function(event) {
    event.waitUntil(
    caches.open(cacheName).then(function(cache) {
    return cache.addAll(filesToCache);
    }).then(function() {
    return self.skipWaiting();
    })
    );
    });

    View Slide

  21. Pre-fetch the App Resources
    var cacheName = 'app-shell-cache-v1';
    var filesToCache = ['/', '/index.html', ...];
    self.addEventListener('install', function(event) {
    event.waitUntil(
    caches.open(cacheName).then(function(cache) {
    return cache.addAll(filesToCache);
    }).then(function() {
    return self.skipWaiting();
    })
    );
    });

    View Slide

  22. Pre-fetch the App Resources
    var cacheName = 'app-shell-cache-v1';
    var filesToCache = ['/', '/index.html', ...];
    self.addEventListener('install', function(event) {
    event.waitUntil(
    caches.open(cacheName).then(function(cache) {
    return cache.addAll(filesToCache);
    }).then(function() {
    return self.skipWaiting();
    })
    );
    });

    View Slide

  23. Pre-fetch the App Resources
    var cacheName = 'app-shell-cache-v1';
    var filesToCache = ['/', '/index.html', ...];
    self.addEventListener('install', function(event) {
    event.waitUntil(
    caches.open(cacheName).then(function(cache) {
    return cache.addAll(filesToCache);
    }).then(function() {
    return self.skipWaiting();
    })
    );
    });

    View Slide

  24. Add an activate Event Handler
    Activated Error
    Idle
    Active Terminated
    Install
    Register

    View Slide

  25. Add an activate Event Handler
    self.addEventListener('activate', function(e) {
    e.waitUntil(
    caches.keys().then(function(keyList) {
    return Promise.all(keyList.map(function(key) {
    if (key !== cacheName) {
    return caches.delete(key);
    }
    }));
    })
    );
    return self.clients.claim();
    });

    View Slide

  26. Add an activate Event Handler
    self.addEventListener('activate', function(e) {
    e.waitUntil(
    caches.keys().then(function(keyList) {
    return Promise.all(keyList.map(function(key) {
    if (key !== cacheName) {
    return caches.delete(key);
    }
    }));
    })
    );
    return self.clients.claim();
    });

    View Slide

  27. Not Done Yet…
    Activated Error
    Idle
    Active Terminated
    Install
    Register

    View Slide

  28. View Slide

  29. Add a fetch Event Handler
    self.addEventListener('fetch', function(e) {
    e.respondWith(
    caches.match(e.request).then(function(response) {
    return response || fetch(e.request);
    })
    );
    });

    View Slide

  30. Add a fetch Event Handler
    self.addEventListener('fetch', function(e) {
    e.respondWith(
    caches.match(e.request).then(function(response) {
    return response || fetch(e.request);
    })
    );
    });

    View Slide

  31. Add a fetch Event Handler
    self.addEventListener('fetch', function(e) {
    e.respondWith(
    caches.match(e.request).then(function(response) {
    return response || fetch(e.request);
    })
    );
    });

    View Slide

  32. Add a fetch Event Handler
    self.addEventListener('fetch', function(e) {
    e.respondWith(
    caches.match(e.request).then(function(response) {
    return response || fetch(e.request);
    })
    );
    });

    View Slide

  33. Ready to Go!
    Activated Error
    Idle
    Active Terminated
    Install
    Register

    View Slide

  34. Scope
    if ('serviceWorker' in navigator) {
    navigator.serviceWorker.register('/service-worker.js')
    .then(function(reg) {
    console.log('Service Worker Registered', reg);
    })
    .catch(function(err) {
    console.log('Error registering Service Worker', err);
    });
    }

    View Slide

  35. Scope
    if ('serviceWorker' in navigator) {
    navigator.serviceWorker.register('/service-worker.js')
    .then(function(reg) {
    console.log('Service Worker Registered', reg);
    })
    .catch(function(err) {
    console.log('Error registering Service Worker', err);
    });
    }

    View Slide

  36. Scope
    if ('serviceWorker' in navigator) {
    navigator.serviceWorker.register('/scripts/s-worker.js')
    .then(function(reg) {
    console.log('Service Worker Registered', reg);
    })
    .catch(function(err) {
    console.log('Error registering Service Worker', err);
    });
    }

    View Slide

  37. Scope
    if ('serviceWorker' in navigator) {
    navigator.serviceWorker.register('/service-worker.js')
    .then(function(reg) {
    console.log('Service Worker Registered', reg);
    })
    .catch(function(err) {
    console.log('Error registering Service Worker', err);
    });
    }

    View Slide

  38. Caching Strategies
    YOU are in control of the network

    View Slide

  39. Cache, Falling Back to Network
    Page
    Service Worker
    Network
    Cache
    X

    View Slide

  40. Network, Falling Back to Cache
    Page
    Service Worker Network
    Cache
    X

    View Slide

  41. Cache, then Network
    Page
    Service Worker Network
    Cache

    View Slide

  42. Generic Fallback
    Page
    Service Worker Network
    Cache
    X
    X

    View Slide

  43. control
    You are in

    View Slide

  44. Tools

    View Slide

  45. Chrome Dev Tools

    View Slide

  46. Chrome Dev Tools: the cache

    View Slide

  47. Chrome Dev Tools: the cache

    View Slide

  48. sw-toolbox

    View Slide

  49. Cache first in sw-toolbox
    importScripts('/sw-toolbox.js');
    toolbox.router.get('/(.*)', toolbox.cacheFirst, {
    origin: /\.googleapis\.com$/
    });

    View Slide

  50. sw-precache Node module

    View Slide

  51. sw-precache
    precache.write('service-worker.js', {
    staticFileGlobs: ['**/*.{html,css}'],
    runtimeCaching: [
    {urlPattern: '/', handler: 'fastest'},
    {urlPattern: '/api/.*', handler: 'networkFirst',
    options: {networkTimeoutSeconds: 5}
    },
    {urlPattern: '/posts/.*', handler: 'cacheFirst'},
    {urlPattern: '/styles/.*', handler: 'cacheOnly'},
    {urlPattern: '/inbox.json', handler: 'networkOnly'}
    ]
    });

    View Slide

  52. PWA Codelab
    https://codelabs.developers.google.com/codelabs/your-first-pwapp

    View Slide

  53. Service Workers
    the core underpinning
    Progressive Web Apps

    View Slide

  54. Service Workers
    Web Apps will need to
    worry about lifecycle...

    View Slide

  55. Thank
    You!

    View Slide