service workers

26
Service Workers Bring your own magic

Upload: jungkees

Post on 27-Aug-2014

288 views

Category:

Software


2 download

DESCRIPTION

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/

TRANSCRIPT

Page 1: Service workers

Service WorkersBring your own magic

Page 3: Service workers

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.

Page 4: Service workers

Installed!Work in progress

Page 5: Service workers

Activating!

https://slightlyoff.github.io/ServiceWorker/spec/service_worker/index.html

https://github.com/slightlyoff/ServiceWorker

Work in progress

Page 6: Service workers

● 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

Page 7: Service workers

Are you online?

Navigation/Resource request

Page

Network fetch

Response

Page 8: Service workers

Are you sufficiently online?

Navigation/Resource request

Page

Network fetch

4XX5XX

TimeoutDNS failure

Page 9: Service workers

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

Page 10: Service workers

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

Page 11: Service workers

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

Page 12: Service workers

// 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

Page 13: Service workers

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");

Page 14: Service workers

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

Page 15: Service workers

Installation: oninstall● In the Service Worker context

// caching.jsthis.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

Page 16: Service workers

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

Page 17: Service workers

● 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

Page 18: Service workers

● In the Service Worker contextthis.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: onfetchFunctional event processing

Page 19: Service workers

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

Page 20: Service workers

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

Page 21: Service workers

Updating triggered by● Registration● Automatic by UA● Successful navigation matching● self.update()

Service Worker Lifecycle

Page 22: Service workers

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

Page 23: Service workers

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

Page 24: Service workers

● 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

Page 25: Service workers

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?”