Service workers

1,960 views
1,665 views

Published on

Service Workers is coming. Bring your own magic with the first programmable cache in your script, and more!

Presented at the GDG Korea DevFest 2014 on the 31st of May 2014: https://sites.google.com/site/gdgdevfestkorea2014/

Published in: Software

Service workers

  1. 1. Service Workers Bring your own magic
  2. 2. Jungkee Song Github: @jungkees Twitter: @jungkees Google+: +JungkeeSong See this slide with animation here!
  3. 3. Service Workers solve .. ● Offline usage ○ Offline-first ○ Sorry, no magic. Create your own! ■ Programmable cache control ■ Custom response - Constructor, IDB, etc. ● Background processing ○ Wanna do things while UA’s not running? ○ Push messages, Alarms (Task Scheduler), BackgroundSync, etc.
  4. 4. Installed! Work in progress
  5. 5. Activating! https://slightlyoff.github.io/ServiceWorker/spec/service_worker/index.html https://github.com/slightlyoff/ServiceWorker Work in progress
  6. 6. ● Lifecycle events Principles and Terms ● Runs on same origin ● Registration keyed by URL scope ● Document is controlled by matching SW upon navigation ● Successfully installed worker is considered worker in waiting ● Functional events
  7. 7. Are you online? Navigation/Resource request Page Network fetch Response
  8. 8. Are you sufficiently online? Navigation/Resource request Page Network fetch 4XX 5XX Timeout DNS failure
  9. 9. fetch event Have a Service Worker? Navigation/Resource request onfetch Page SW Cache self.caches.match(url) Promise<response> e.respondWith (Promise<response>) IDB new Response({ status: 200, body: { … } }) Offline-first
  10. 10. fetch event Now fallback to network with SW Navigation/Resource request onfetch Page SW Cache self.fetch(request) self.caches.match(url) Promise rejects e.respondWith (Promise<response>) Offline-first
  11. 11. fetch event Event-driven worker Navigation/Resource request onfetch Page SW Cache self.caches.match(url) Promise<response> e.respondWith (Promise<response>) Page Page Navigation/Resource request fetch event e.respondWith (Promise<response>) Key concept
  12. 12. // scope defaults to "/*" navigator.serviceWorker.register("/assets/v1/serviceworker.js").then( function(serviceWorker) { console.log("success!"); serviceWorker.postMessage("Howdy from your installing page."); // To use the serviceWorker immediately, you might call // window.location.reload() }, function(why) { console.error("Installing the worker failed!", why); }); Registration ● In the page “/*” /assets/v1/serviceworker.js [ Registration map ] Scope Script URL Service Worker Lifecycle
  13. 13. Registration ● In the page navigator.serviceWorker.register("/sw.js"); “/*” /sw.js [ Registration map ] Scope Script URL “/foo/*” /foo/sw.js “/*” /bar/sw.js Service Worker Lifecycle navigator.serviceWorker.register("/foo/sw.js", { scope: “/foo/*” }); navigator.serviceWorker.register("/bar/sw.js");
  14. 14. Installation ● Registration triggers installation of the SW ● UA fires install event to the installing Service Worker ● The event handler may extend the lifetime of SW for preparing its caches Service Worker Lifecycle
  15. 15. Installation: oninstall ● In the Service Worker context // caching.js this.addEventListener("install", function(e) { // Create a cache of resources. Begins the process of fetching them. var shellResources = new Cache(); // The coast is only clear when all the resources are ready. e.waitUntil(shellResources.add( "/app.html", "/assets/v1/base.css", "/assets/v1/app.js", "/assets/v1/logo.png", "/assets/v1/intro_video.webm", )); // Add Cache to the global so it can be used later during onfetch self.caches.set("shell-v1", shellResources); }); Service Worker Lifecycle
  16. 16. Programmable cache control ● new Cache() [Constructor] interface Cache { Promise<AbstractResponse> match((Request or ScalarValueString) request, optional QueryParams params); Promise<sequence<AbstractResponse>> matchAll((Request or ScalarValueString) request, optional QueryParams params); Promise<any> add((Request or ScalarValueString)... requests); Promise<any> put((Request or ScalarValueString) request, AbstractResponse response); Promise<any> delete((Request or ScalarValueString) request, optional QueryParams params); Promise<any> each(CacheIterationCallback callback, optional object thisArg); }; Service Worker Lifecycle
  17. 17. ● Worker in waiting ○ Once self.oninstall() ends ○ So to speak, the installation successfully done ○ This is not yet controlling the documents in scope ● navigator.serviceWorker.controller ○ When all the active documents in scope unload ○ The worker in waiting becomes active worker ○ self.clients.reloadAll() works ○ event.replace() works Have a controller yet? Service Worker Lifecycle
  18. 18. ● In the Service Worker context this.addEventListener("fetch", function(e) { // No "onfetch" events are dispatched to the ServiceWorker until it // successfully installs. // All operations on caches are async, including matching URLs, so we use // Promises heavily. e.respondWith() even takes Promises to enable this: e.respondWith( caches.match(e.request).catch(function() { return e.default(); }).catch(function() { return caches.match("/fallback.html"); }) ); }); Handle a fetch: onfetch Functional event processing
  19. 19. Fetch: navigation request onfetch sw.js Cache self.caches.match(url) Promise<response> e.respondWith (Promise<response>) “/*” /sw.js [ Registration map ] Scope Script URL “/foo/*” /foo/sw.js Page Hit “https://example.com/index.html fetch event Scope matching Run SW Functional event processing
  20. 20. Fetch: subresource request onfetch sw.js Cache self.caches.match(url) Promise<response> e.respondWith (Promise<response>) “/*” /sw.js [ Registration map ] Scope Script URL “/foo/*” /foo/sw.js Page Fetch “https://example.com/img/flower.png fetch event Control Run SW Functional event processing
  21. 21. Updating triggered by ● Registration ● Automatic by UA ● Successful navigation matching ● self.update() Service Worker Lifecycle
  22. 22. Updating onfetch sw-v2 Cache self.caches.match(url) Promise<response> e.respondWith (Promise<response>) “/*” /sw-v1 [ Registration map ] Scope active fetch event - waiting Page sw-v1 _Update _Install Page sw-v1 /sw-v2 /sw-v2- Page sw-v2 Fetch “https://example.com/img/flower.png Run SW Service Worker Lifecycle
  23. 23. Security ● Origin relativity ● Cross origin resource ● HTTPS-only? ○ Protect end users from man-in-the-middle attacks ○ Existing "playground" services (e.g. github.io) now work with HTTPS ○ HTTPS is coming across much more of the web quickly ○ Devtools can loosen the restriction for development
  24. 24. ● Event-driven workers ○ Free to shutdown the worker when handler’s done ○ “Write your workers as though they will die after every request” ● Keep the onactivate short ● Platform considerations ○ Enhance matching navigation ○ Events implicitly filter ○ Enhance startup Performance
  25. 25. Is it ready for you? ● Chrome Canary ○ Partial under flag ○ chrome://flags/#enable-service-worker ● Firefox Nightly ○ Partial under flag ○ about:config > dom.serviceWorkers.enabled ● Stay alerted! ○ Jake’s “Is ServiceWorker ready?”
  26. 26. References and Practices ● Service Worker - first draft published - Jake Archibald ● Specification ● Github’s explainer ● Github’s implementation considerations

×