Skip to content

Instantly share code, notes, and snippets.

@bnguyensn
Last active October 29, 2019 21:55
Show Gist options
  • Save bnguyensn/65f3b82b34eede4e3cbfe1a7142e2e64 to your computer and use it in GitHub Desktop.
Save bnguyensn/65f3b82b34eede4e3cbfe1a7142e2e64 to your computer and use it in GitHub Desktop.
Service worker notes

Service worker notes

Requirements

Lifecycle

1. Registration

  • Browser sends a request to download the service worker registration script as well as the service worker file (for the first time)
  • Browser registers the service worker via the service worker registration script:
    • navigator.serviceWorker.register('/path-to-service-worker-file.js')

2. Installation (event: install) (1st time)

  • The service worker fires an install event after a successful registration
  • The service worker opens all file caches (and finds that there're no caches):
    • caches.open('name-of-cache')
  • The service worker creates a new file cache using the files' URLs:
    • cache.addAll(urlArray)
    • This is also called "precaching"
  • IF:
    • all files successfully cache, then the install event finishes successfully
    • a file fails to cache, then the install event fails

Be careful

  • ⚠️ The more files that need to be cached, the higher the chance of installation failure

3. Activation (event: activate) (1st time)

  • The service worker fires an activate event after a successful install
  • Normally nothing happens during the 1st activate event callback

4. Network requests (event: fetch)

  • After a successful activation, the service worker fires fetch events every time the web page refreshses or is navigated
  • The service worker can compare the Request object with its file caches here (caches.match()). IF:
    • There is a cached file matching what is being requested, the service worker can respond to the network request with the cached file.
    • There are no matching cached files. The service worker helps the web page fetch the file normally
    • Either way, event.respondWith() is used
  • This is where Workbox Routing comes in:
    • A Route consists of 2 functions: "matching" and "handling":
      • matching function: ({urlObj, fetchEventObj}) => url.pathname === 'path/to/match'
      • handling function: ({urlObj, fetchEventObj, matchingFnReturnValue}) => { // Return a Promise<Response> }
    • No asynchronous actions can be performed in the matching function
    • The matching function can be a regex: new RegExp('some-regex')
    • The Response object that the handling function's Promise resolves to can come from the network, the file caches, or self-generated from the service worker
    • The handling function can be substituted with a Workbox strategy
    • We register a Route like this:
      • workbox.routing.registerRoute(matchingFn, handlingFn)
      • workbox.routing.registerNavigationRoute(handlingFn, {whitelist, blacklist}) (for single-page applications)
    • Workbox Routes can be defined as GET (default) or POST or any other HTTP methods
    • If multiple Routes match a network request, the Route that is registered first is used

5. Activation (event: activate) (subsequently)

  • Browser sends a request to re-download the service worker file
  • Browser detects a difference between the current and the newly downloaded service worker file
  • The new service worker fires an install event
  • Upon successful installation, the new service worker enters a waiting state because the old service worker is still controlling the web page
  • The new service worker takes over the old one's web page control upon page reload. The new service worker fires an activate event
    • Old caches should be replaced with new ones during the activate event callback

Considerations

Resource delivery speed vs. resource freshness

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment