Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Service Workers

Service Workers

Service workers bring amazing new capabilities to the web. They make fully offline web apps possible, improve performance, and bring more resilience and stability to any site. In this talk, you'll learn how these man-in-the-middle attacks on your own site work, different approaches you can use, and how they might replace many of our current best practices.

Df5f3b6aeb1caacc0acabf2cb45264da?s=128

Chris Ferdinandi

May 04, 2021
Tweet

Transcript

  1. @ChrisFerdinandi GoMakeThings.com How to run a man-in-the-middle attack on your

    own site for fun and profit SERVICE WORKERS
  2. We’ve broken the web

  3. JavaScript is a house of cards

  4. None
  5. ~3x increase in bandwidth over the last five years https://www.speedtest.net

  6. Loading…

  7. Bandwidth is not evenly distributed

  8. None
  9. Chris Ferdinandi GoMakeThings.com

  10. None
  11. Start End 1 What service workers are
 (and how they

    work) Cool things you can do 3 Strategies 2
  12. What is a sevice worker? 1

  13. None
  14. {SW}

  15. // Initialize the service worker
 //(load this with the rest

    of your JS) if (navigator && navigator.serviceWorker) { navigator.serviceWorker.register('/sw.js'); }
  16. Install & Activate

  17. {SW}

  18. // listen for requests addEventListener('fetch', function (event) { // Do

    something with the request... });
  19. {SW}

  20. A service worker is a man-in-the-middle attack on your own

    website (but like… a good one)
  21. SSL Required

  22. Service Worker Strategies 2

  23. Two Approaches Network-First Offline-First

  24. {SW} Network-First

  25. addEventListener('fetch', (event) => { let request = event.request; request.respondWith( fetch(request).then((response)

    => { let copy = response.clone(); event.waitUntil(caches.open('app').then((cache) => { return cache.put(request, copy); })); return response; }).catch((error) => { return caches.match(request).then((response) => { return response; }); }) ); });
  26. addEventListener('fetch', (event) => { let request = event.request; request.respondWith( fetch(request).then((response)

    => { let copy = response.clone(); event.waitUntil(caches.open('app').then((cache) => { return cache.put(request, copy); })); return response; }).catch((error) => { return caches.match(request).then((response) => { return response; }); }) ); });
  27. addEventListener('fetch', (event) => { let request = event.request; request.respondWith( fetch(request).then((response)

    => { let copy = response.clone(); event.waitUntil(caches.open('app').then((cache) => { return cache.put(request, copy); })); return response; }).catch((error) => { return caches.match(request).then((response) => { return response; }); }) ); });
  28. addEventListener('fetch', (event) => { let request = event.request; request.respondWith( fetch(request).then((response)

    => { let copy = response.clone(); event.waitUntil(caches.open('app').then((cache) => { return cache.put(request, copy); })); return response; }).catch((error) => { return caches.match(request).then((response) => { return response; }); }) ); });
  29. Network-First best for frequently updated assets {[0]}

  30. {SW} Offline-First

  31. addEventListener('fetch', (event) => { let request = event.request; request.respondWith( caches.match(request).then((response)

    => { return response || fetch(request).then((response) => { let copy = response.clone(); event.waitUntil(caches.open('app').then((cache) => { return cache.put(request, copy); })); return response; }); }) ); });
  32. addEventListener('fetch', (event) => { let request = event.request; request.respondWith( caches.match(request).then((response)

    => { return response || fetch(request).then((response) => { let copy = response.clone(); event.waitUntil(caches.open('app').then((cache) => { return cache.put(request, copy); })); return response; }); }) ); });
  33. addEventListener('fetch', (event) => { let request = event.request; request.respondWith( caches.match(request).then((response)

    => { return response || fetch(request).then((response) => { let copy = response.clone(); event.waitUntil(caches.open('app').then((cache) => { return cache.put(request, copy); })); return response; }); }) ); });
  34. addEventListener('fetch', (event) => { let request = event.request; request.respondWith( caches.match(request).then((response)

    => { return response || fetch(request).then((response) => { let copy = response.clone(); event.waitUntil(caches.open('app').then((cache) => { return cache.put(request, copy); })); return response; }); }) ); });
  35. Offline-First best for static assets that don’t change much

  36. {SW} Fallbacks (Network-First)

  37. {SW} Fallbacks (Offline-First)

  38. addEventListener('install', (event) => { event.waitUntil(caches.open('app').then((cache) => { cache.add(new Request('/offline/')); return

    cache; })); }); // Inside the fetch event… catch((error) => { return caches.match(request).then((response) => { return response || caches.match('/offline/'); }); });
  39. Uses & Examples 3

  40. Lil’ Rhody Seafood Looks like you're offline. Here's the important

    stuff… 401-555-5555 123 Lobster Drive Narragansett, RI Weekly Specials Clam Cakes - $5 Lobster Rolls - $7 Calamari - $7 Clam Chowder - $5/$8 Del’s Lemonade - $3 Show critical info when offline • Restaurants • Conferences • Hotels
  41. Cache previously viewed pages • Reference Sites • News Sites

    • Social Networks • Utility Apps
  42. Cache core assets for performance • CSS • JavaScript •

    Images • Fonts 🚀
  43. 🚀 Go Fully Offline • Apps • Games

  44. Replace SPAs with MPAs

  45. None
  46. None
  47. Homepage Login Dashboard Account

  48. You can still render HTML with JavaScript

  49. None
  50. {"} {SW} Caching API Calls (with an expiration date)

  51. None
  52. None
  53. None
  54. If you only remember one thing…

  55. JavaScript is a house of cards

  56. None