Share
Embed
Why we chose Service Worker API
majek04
November 16, 2017
Transcript
50 slides
-
Programming on the Edge: Why we chose Service Worker API?
Marek Majkowski @majek04 -
Reverse proxy 3 Eyeball Reverse proxy Origin server • Optimizations
• Caching • DDoS protection • Security -
Two problems • A/ Configuration gets more complex over time
• Wants to be a programming language • B/ Configuration is tied to server • Specific nomenclature phases/hooks 6 -
Messy configuration • General problem • Apache, Nginx, Lighttpd, all
started with clean configs • Varnish has VCL • Syntax resembles programming language 9 -
Two problems • A/ Configuration gets more complex over time
• Wants to be a programming language • B/ Configuration is tied to server • Specific nomenclature phases/hooks 11 -
Offline web apps • Google Gears • ApplicationCache • Service
Worker API • Buzzword: PWA Progressive Web Apps 16 -
ServiceWorkers Service workers essentially act as proxy servers that sit
between web applications, and the browser and network (when available). They are intended to (amongst other things) enable the creation of effective offline experiences, intercepting network requests and taking appropriate action based on whether the network is available and updated assets reside on the server. They will also allow access to push notifications and background sync APIs. 19 -
20 • install + waitUntil (seamless worker upgrade) • note:
skipWaiting • activate • message • fetch • push • sync Events -
Hint • > P.S.: Chrome (normally) won't stop a service
worker while you have its DevTools interface open, but this is only to ease debugging and is not behavior you should rely on for a real application. 22 -
Debugging • Opera browser://serviceworker-internals • FF about:serviceworkers • Chrome: Application
panel in devtools • chrome://inspect/#service-workers • chrome://serviceworker-internals 24 -
Service Workers • Chrome 40 (Jan 2015) • Firefox 44
(Jan 2016) • https://jakearchibald.github.io/isserviceworkerready/ 26 -
Promises all the way! • All API's take and return
promises • ServiceWorker must be over HTTPS • no localstorage (sync) • no DOM access • IndexedDB is there • Isn’t tied to a particular page • https://github.com/w3c/ServiceWorker/blob/master/ 28 -
unregister 30 navigator.serviceWorker.getRegistrations().then( registrations => { for(let registration of registrations)
{ registration.unregister() } }) -
fetch • method, body, integrity • headers: {} • mode:
'cors', 'no-cors', 'same-origin', 'navigate' • cache: 'default', 'no-store', 'reload', 'force-cache'.... • redirect: 'follow', 'error', 'manual' • credentials: 'include', 'same-origin', 'omit' • referrer: 'no-referrer', 'client' 33 -
34 addEventListener('fetch', event => { var r = new Response('Bye
bye world!') event.respondWith(r) }) Response -
What can possibly go wrong • Service worker goes through
service worker..... • > If you force-reload the page (shift-reload) it bypasses the service worker entirely. It'll be uncontrolled. This feature is in the spec, so it works in other service- worker-supporting browsers. 35 -
37 addEventListener('fetch', event => { console.log(event.request); if (event.request.url == 'http://localhost:8080/other.html')
{ event.respondWith(new Response('Bye bye world!')) } else { event.respondWith(fetch(event.request)) } }); fetch -
CacheStorage vs Cache 38 caches.match(event.request).then( response => { if (response)
return response; return fetch(event.request).then( r => { caches.open('v1').then( cache => {cache.put(event.request, r);} ); return r.clone(); }); }).catch(function() { return caches.match('/sw-test/gallery/myLittleVader.jpg'); }); -
sync 39 // main navigator.serviceWorker.ready.then(function(swRegistration) { return swRegistration.sync.register('leaderboard'); }); //
sw.js self.addEventListener('sync', function(event) { if (event.id == 'leaderboard') { event.waitUntil( caches.open('mygame-dynamic').then(function(cache) { return cache.add('/leaderboard.json'); }) ); } }); -
Service workers • Service worker • MITM - TLS only
• Fetch • Cache • Sync • Push 40 -
Two problems • A/ Configuration gets more complex over time
• Wants to be a programming language • B/ Configuration is tied to server • Specific nomenclature phases/hooks 43 -
46 addEventListener('fetch', event => { var url = new URL(event.request.url)
url.scheme = 'https'; url.hostname = 'www.google.com'; event.respondWith(fetch(url.toString())); }) -
47 // A Service Worker which replaces the word "Worker"
with // "Minion" in all site content. addEventListener("fetch", event => { event.respondWith(fetchAndReplace(event.request)) }) async function fetchAndReplace(request) { // Fetch from origin server. let response = await fetch(request) // Make sure we only modify text, not images. let type = response.headers.get("Content-Type") || "" if (!type.startsWith("text/html")) { // Not text. Don't modify. return response } // Read response body. let text = await response.text() // Modify it. let modified = text.replace(/(Java|Cloud)/g, "Butt") // Return modified response. return new Response(modified, { status: response.status, statusText: response.statusText, headers: response.headers }) } -
ReadableStream 48 const stream = new ReadableStream({ start(controller) { interval
= setInterval(() => { let string = randomChars(); // Add the string to the stream controller.enqueue(string); // show it on the screen let listItem = document.createElement('li'); listItem.textContent = string; list1.appendChild(listItem); }, 1000); button.addEventListener('click', function() { clearInterval(interval); fetchStream(); controller.close(); }) }, pull(controller) { // We don't really need a pull in this example }, cancel() { // This is called if the reader cancels, // so we should stop generating strings clearInterval(interval); } }); -
Opportunity to practice • Promises (integration with browser events) •
ES6 arrow functions • Async/await • Streams 50