Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Service Worker registration & lifecycle

Jxck
May 18, 2016

Service Worker registration & lifecycle

Step forward Understanding Service Worker Registration & Lifecycle
at Frontend Meetup Tokyo vol.2 2016/5/18
Jxck

Jxck

May 18, 2016
Tweet

More Decks by Jxck

Other Decks in Technology

Transcript

  1. • id: Jxck • github: Jxck • twitter: @jxck_ •

    blog: https://blog.jxck.io • podcast: http://mozaic.fm • Love: music Jack
  2. Next Step of Introduction 6 • Go Deeper / Understand

    Examples Well • Good Introductions ◦ https://serviceworke.rs/ ◦ https://jakearchibald.com/2014/offline-cookbook/ ◦ http://www.html5rocks.com/ja/tutorials/service- worker/introduction/ ◦ More • Focus on … ◦ Registration ◦ Update ◦ Scope
  3. Workers class Hero 8 • Service Worker (got back together)

    • Shared Worker • Web Worker • App Cache (broke up)
  4. I'm free to be whatever I 何になるのも俺の自由だ Whatever I choose

    何を選ぶのも俺の自由だ And I'll hook the request if I want その気になればリクエストだってフックしてやる 9 https://youtu.be/zUADzarhFyA
  5. 13 Event with Client • Controller hooks HTTP request from

    Client • Controller talks with Client via message
  6. 14 Event with Network • Controller hooks push from network

    • Controller hooks change from offline -> online
  7. 16 worker/db • Controller also Use WebWorker / IndexedDB •

    No LocalStorage because Sync I/O • Separate Context between Client
  8. 17 cache • Client/Controller has Cache API • Before browser

    cache • Means fetch from SW hits browser cache
  9. register() navigator.serviceWorker.register('worker.js') .then((registration) => { return navigator.serviceWorker.ready; }); 22 self.addEventListener('install',

    (e) => { console.info('install', e); }); self.addEventListener('activate', (e) => { console.info('activate', e); }); master.js worker.js
  10. register() -> oninstall 23 • Browser fetches script • Install

    it • Fires oninstall • Prepare cache or migrate schema Ver. 1
  11. installed -> waiting 24 • Installed script moves to waiting

    • Waiting waits to be active • If no active script available, through to active Ver. 1
  12. waiting -> activate 25 • waiting script moves to active

    • Fires onactivate • but Not Controller yet Ver. 1
  13. Be a Controller 26 • If there has a chance

    to be controller • Script became controller • Fires oncontrollerchange Ver. 1
  14. Chance to be Controlle ? 27 • Avoid state conflict

    between current controller and next controller • Next page load • call claim() Ver. 1
  15. skipWaiting/claim self.addEventListener('activate', (e) => { console.info('activate', e); // make me

    controller immediately !! e.waitUntil(self.clients.claim()); }); 28 navigator.serviceWorker.register('worker.js') .then((registration) => { return navigator.serviceWorker.ready; }); master.js worker.js
  16. update() navigator.serviceWorker.register('v1.js') .then((reg) => { reg.addEventListener('updatefound', (e) => { console.info('update',

    e); // v2 found }); return navigator.serviceWorker.ready; }).then((registration) => { setInterval(() => { // update registration.update(); }, 1000); }); 30
  17. update() or reload 31 • reload / call update() fetches

    script again • If script changed(v2), install again • Fires onupdatefound Ver. 2
  18. update() and browser cache 32 • update() hits browser cache

    • But bypass(max-age) it after 24h • Security knowledge from App Cache Cached Ver. 1 Ver. 2
  19. waiting 33 • Installed v2 became waiting (v1) • If

    activate v2 immediatly, call skipWaiting() Ver. 1 Ver. 2
  20. oninstall/onactivate self.addEventListener('install', (e) => { console.info('install', e); // do some

    prepare not affect to v1 // like cache new resouce etc }); self.addEventListener('activate', (e) => { console.info('activate', e); // do some cleanup of v1 // like schema update etc }); 34
  21. skipWaiting/claim self.addEventListener('install', (e) => { console.info('install', e); // make me

    active immediately !! e.waitUntil(skipWaiting()); }); self.addEventListener('activate', (e) => { console.info('activate', e); // make me controller immediately !! e.waitUntil(self.clients.claim()); }); 36
  22. 37 When worker works ? • Works even if offline

    • Works even if page not opened • Works even if browser closed
  23. 38 When worker stops ? • Active worker stops anytime

    while no event • Restart when event fired • Save Every Data into Storage (not on memory)
  24. register() with scope navigator .serviceWorker .register('worker.js', { scope: '.' })

    .then((registration) => { return navigator.serviceWorker.ready; }); 40 master.js • Controller controls client in scope • Could register multiple controller in different scope • But only one Controller for Client always
  25. Scope 41 • Browser searches controller for client • Wide

    scope affects deep path • Deep match with path & scope
  26. Scope 42 • If you avoid sw in deep path

    ◦ If-else in controller ◦ Register emtpy SW cache.js cache-push.js empty.js
  27. Service Worker Allowed 43 • /js/worker.js can’t register /foo ◦

    Only /js/* are allowed ◦ Add Service Worker Allowed: “/foo” as HTTP header
  28. On insecure origin 45 $ google_chrome \ --user-data-dir=/path/to/js \ --unsafely-treat-

    insecure-origin-as-secure=http://insecure.example. com • Register SW to insecure origin • For Develop only • But Let’s Encrypt it
  29. tips 46 • Be friend with Chrome Canaly Dev Tools

    • Always Check registration & update • Design Scope Carefully • Maintain Cache Carefully • Never forget save to DB while event lifetime • Basiclly no code outside event handler • Start with Implicit Proxy ◦ Local Implicit proxy: works same w/o sw ◦ Local Orgin Server: generate contents in sw • Push is not only usecase for sw