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. Service Worker
    registration/lifecycle
    Frontend Meetup Tokyo vol.2 2016/5/18
    Jxck

    View full-size slide

  2. ● id: Jxck
    ● github: Jxck
    ● twitter: @jxck_
    ● blog: https://blog.jxck.io
    ● podcast: http://mozaic.fm
    ● Love: music
    Jack

    View full-size slide

  3. mozaic.fm ep17
    3
    Service Worker w/ @kinu, @nhiroki_
    http://mozaic.fm/post/117004083098/17-service-worker

    View full-size slide

  4. 中級者向け Service Worker Tutorial
    4
    https://blog.jxck.io/entries/2016-04-24/service-worker-tutorial.html

    View full-size slide

  5. Todays Talk
    5

    View full-size slide

  6. 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

    View full-size slide

  7. Service Worker
    7

    View full-size slide

  8. Workers class Hero
    8
    ● Service Worker (got back together)
    ● Shared Worker
    ● Web Worker
    ● App Cache (broke up)

    View full-size slide

  9. I'm free to be whatever I
    何になるのも俺の自由だ
    Whatever I choose
    何を選ぶのも俺の自由だ
    And I'll hook the request if I want
    その気になればリクエストだってフックしてやる
    9
    https://youtu.be/zUADzarhFyA

    View full-size slide

  10. Architecture
    10

    View full-size slide

  11. 11
    Architecture

    View full-size slide

  12. 12
    Controller/Client
    ● Controller controls Client
    ○ Client = Window
    ○ Controller = Service Worker

    View full-size slide

  13. 13
    Event with Client
    ● Controller hooks HTTP request from Client
    ● Controller talks with Client via message

    View full-size slide

  14. 14
    Event with Network
    ● Controller hooks push from network
    ● Controller hooks change from offline -> online

    View full-size slide

  15. 15
    websocket
    ● Controller doesn’t hooks client WebSocket
    ● Controller also talks WebSocket

    View full-size slide

  16. 16
    worker/db
    ● Controller also Use WebWorker / IndexedDB
    ● No LocalStorage because Sync I/O
    ● Separate Context between Client

    View full-size slide

  17. 17
    cache
    ● Client/Controller has Cache API
    ● Before browser cache
    ● Means fetch from SW hits browser cache

    View full-size slide

  18. 18
    Architecture

    View full-size slide

  19. Install SW
    21

    View full-size slide

  20. 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

    View full-size slide

  21. register() -> oninstall
    23
    ● Browser fetches
    script
    ● Install it
    ● Fires oninstall
    ● Prepare cache or
    migrate schema
    Ver. 1

    View full-size slide

  22. installed -> waiting
    24
    ● Installed script moves to waiting
    ● Waiting waits to be active
    ● If no active script available, through to active
    Ver. 1

    View full-size slide

  23. waiting -> activate
    25
    ● waiting script moves to active
    ● Fires onactivate
    ● but Not Controller yet
    Ver. 1

    View full-size slide

  24. Be a Controller
    26
    ● If there has a
    chance to be
    controller
    ● Script became
    controller
    ● Fires
    oncontrollerchange
    Ver. 1

    View full-size slide

  25. Chance to be Controlle ?
    27
    ● Avoid state conflict
    between current
    controller and next
    controller
    ● Next page load
    ● call claim()
    Ver. 1

    View full-size slide

  26. 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

    View full-size slide

  27. 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

    View full-size slide

  28. update() or reload
    31
    ● reload / call update() fetches script again
    ● If script changed(v2), install again
    ● Fires onupdatefound
    Ver. 2

    View full-size slide

  29. 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

    View full-size slide

  30. waiting
    33
    ● Installed v2 became waiting (v1)
    ● If activate v2 immediatly, call skipWaiting()
    Ver. 1
    Ver. 2

    View full-size slide

  31. 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

    View full-size slide

  32. waiting
    35
    ● Redundant old controller & oncontrollerchange
    Ver. 1
    Ver. 2

    View full-size slide

  33. 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

    View full-size slide

  34. 37
    When worker works ?
    ● Works even if offline
    ● Works even if page not opened
    ● Works even if browser closed

    View full-size slide

  35. 38
    When worker stops ?
    ● Active worker stops anytime while no event
    ● Restart when event fired
    ● Save Every Data into Storage (not on memory)

    View full-size slide

  36. 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

    View full-size slide

  37. Scope
    41
    ● Browser searches controller for client
    ● Wide scope affects deep path
    ● Deep match with path & scope

    View full-size slide

  38. Scope
    42
    ● If you avoid sw in deep path
    ○ If-else in controller
    ○ Register emtpy SW
    cache.js
    cache-push.js
    empty.js

    View full-size slide

  39. Service Worker Allowed
    43
    ● /js/worker.js can’t register /foo
    ○ Only /js/* are allowed
    ○ Add Service Worker Allowed: “/foo” as HTTP header

    View full-size slide

  40. 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

    View full-size slide

  41. 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

    View full-size slide