Instant Loading with Service Workers (Chrome Dev Summit '15)

Instant Loading with Service Workers (Chrome Dev Summit '15)

Presentation video: https://www.youtube.com/watch?v=jCKZDTtUA2A

Service workers can power your web app while offline, but they can also offer substantial performance benefits while online. We’ll explain how to structure your web app to optimize load time for initial and return visitors, and cover helpful service worker libraries that minimize the amount of boilerplate code you’ll have to write.

6fd3d2d77a1bb4cad9d07741dac08c9f?s=128

Jeffrey Posnick

November 17, 2015
Tweet

Transcript

  1. None
  2. Instant Loading with Service Workers Jeff Posnick @jeffposnick

  3. App Shell + Service Worker

  4. ifixit-pwa.appspot.com

  5. ifixit-pwa.appspot.com 2G Network, first visit ~ 650ms for above-the-fold

  6. ifixit-pwa.appspot.com 2G Network, second visit ~ 200ms for above-the-fold (~

    560ms w/o service worker)
  7. ifixit-pwa.appspot.com 2G Network, new page ~ 225ms for above-the-fold (~

    650ms w/o service worker)
  8. Take the Network Out of the Picture

  9. 1 second delay in page times leads to 11% fewer

    page views 16% decrease in customer satisfaction goo.gl/SOR47G
  10. What’s an App Shell?

  11. Anatomy of an App Shell /shell HTML + styles.css Styles

    app.js JavaScript = Shell
  12. Populating an App Shell iFixit API Content Shell

  13. What’s a Service Worker?

  14. An Air Traffic Controller for Your Requests

  15. The Life of a Service Worker No Service Worker install

    Event ↪ Cache the App Shell!
  16. GET /shell

  17. template placeholder Service Worker Installation site-wide styles Contents of /shell

    site-wide JS <head> <style> /* inline styles */ </style> </head> <body> <!-- template insertion point --> <script src="app.js"> </body> Shell
  18. The Life of a Service Worker No Service Worker install

    Event activate Event Idle fetch Event ↪ Cache Clean Up ↪ Handle Network Requests Stopped Stopped
  19. Service Worker fetch Interception GET /guide/456 fetch Event /shell (from

    cache) Shell
  20. Service Workers without the Work sw-precache Shell sw-toolbox Content

  21. Service Workers without the Work Case Study: goo.gl/HD6ngC

  22. sw-precache for Your App Shell sw-precache + = github.com/GoogleChrome/sw-precache npm

    install --save-dev sw-precache Shell
  23. sw-precache in Action Shell // [file, hash] pairs ... [js/app.js,

    hashABC] ... [styles/all.css, hash123] // Service worker code service-worker.js build/{images,js,styles}/**/*
  24. sw-precache in Action: Updates Shell // [file, hash] pairs ...

    [js/app.js, hashXYZ] ... [styles/all.css, hash789] // Service worker code service-worker.js
  25. sw-precache Command-line Interface Shell $ npm install -g sw-precache $

    sw-precache --verbose Caching static resource "./images/back.png" (151 B) Caching static resource "./js/app.js" (319.06 kB) Caching static resource "./js/register-service-worker.js" (546 B) Caching static resource "./js/third-party.js" (245.03 kB) Caching static resource "./service-worker.js" (8.59 kB) Caching static resource "./styles/all.css" (1.82 kB) Total precache size is about 575.19 kB for 6 resources. service-worker.js has been generated with the service worker contents.
  26. gulp.babel.js Shell App Shell Template Partials/Inlines Request Redirection App Shell

    External Styles/Images/JS sw-toolbox Import swPrecache.write('service-worker.js', { dynamicUrlToDependencies: { '/shell': [...glob.sync(`${BUILD_DIR}/rev/js/**/*.js`), ...glob.sync(`${BUILD_DIR}/rev/styles/all*.css`), `${SRC_DIR}/views/index.handlebars`] }, navigateFallback: '/shell', staticFileGlobs: [ `${BUILD_DIR}/rev/js/**/*.js`, `${BUILD_DIR}/rev/styles/all*.css`], importScripts: [`${BUILD_DIR}/sw/sw-toolbox.js`], });
  27. sw-toolbox for Your Dynamic Content sw-toolbox github.com/GoogleChrome/sw-toolbox npm install --save-dev

    sw-toolbox Content
  28. Strategy: Cache-first, Network-fallback Content toolbox.cacheFirst

  29. Strategy: Network-first, Cache-fallback Content toolbox.networkFirst

  30. Strategy: Cache/Network Race Content toolbox.fastest

  31. Thinking Strategically Content toolbox.router.get('/images', toolbox.cacheFirst); toolbox.router.get('/api', toolbox.networkFirst); toolbox.router.get('/profile', toolbox.fastest);

  32. Why use sw-toolbox?

  33. Battle Lie-Fi! Content toolbox.router.get( '/path/to/image', toolbox.networkFirst, {networkTimeoutSeconds: 3} );

  34. Rein in Your Caches! Content toolbox.router.get( '/path/to/images/.*', toolbox.cacheFirst, {cache: {

    name: 'images', maxEntries: 6 }} );
  35. sw-toolbox-config.js Content iFixit API Route toolbox.fastest fallback logic Image Route

    toolbox.cacheFirst LRU cache expiration toolbox.router.get('/api/2.0/(.*)', toolbox.fastest, { origin: /^https:\/\/www.ifixit.com$/ }); const MISSING_IMAGE = '/images/missing.png'; toolbox.cache(MISSING_IMAGE); function imageHandler(request, values, options) { return toolbox.cacheFirst(request, values, options).catch(() => { return caches.match(MISSING_IMAGE); }); } toolbox.router.get('/(.*)', imageHandler, { cache: {name: 'image-cache', maxEntries: 50}, origin: /cloudfront.net$/ });
  36. if (‘serviceWorker’ in navigator) { navigator.serviceWorker.register(‘sw.js’); } else { //

    But not all browsers // support service workers! }
  37. Air Traffic Controllers as Progressive Enhancement(?!?)

  38. Initial Visit

  39. Next Visit: Service Worker Supported

  40. Next Visit: Service Worker Not Supported

  41. HTTP Caching Best Practices Still Apply ✓ Add hashes to

    resource file names in your build ↪ /styles/all.css → /styles/all.ed34c56.css ✓ Use far-future HTTP caching headers ↪ Cache-Control: max-age=31536000 Still plays nicely with sw-precache!
  42. Service Workers FTW! But, service workers let you: ✓ Serve

    the HTML for the landing page cache-first... ✓ ...even if that page is server-rendered.
  43. Next Steps:

  44. Embrace Your Shell!

  45. iFixit API Demo ifixit-pwa.appspot.com github.com/GoogleChrome/sw-precache/ tree/master/app-shell-demo

  46. sw-precache Codelab www.code-labs.io/codelabs/sw-precache/

  47. Polymer Demo zuperkulblog.appspot.com github.com/polymerlabs/ zuperkulblog-progressive

  48. github.com/Google/web-starter-kit

  49. “Vanilla JS” App Shell app-shell.appspot.com github.com/GoogleChrome/application-shell

  50. Instant Loading with Service Workers Jeff Posnick @jeffposnick

  51. None