Slide 1

Slide 1 text

No content

Slide 2

Slide 2 text

Instant Loading with Service Workers Jeff Posnick @jeffposnick

Slide 3

Slide 3 text

App Shell + Service Worker

Slide 4

Slide 4 text

ifixit-pwa.appspot.com

Slide 5

Slide 5 text

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

Slide 6

Slide 6 text

ifixit-pwa.appspot.com 2G Network, second visit ~ 200ms for above-the-fold (~ 560ms w/o service worker)

Slide 7

Slide 7 text

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

Slide 8

Slide 8 text

Take the Network Out of the Picture

Slide 9

Slide 9 text

1 second delay in page times leads to 11% fewer page views 16% decrease in customer satisfaction goo.gl/SOR47G

Slide 10

Slide 10 text

What’s an App Shell?

Slide 11

Slide 11 text

Anatomy of an App Shell /shell HTML + styles.css Styles app.js JavaScript = Shell

Slide 12

Slide 12 text

Populating an App Shell iFixit API Content Shell

Slide 13

Slide 13 text

What’s a Service Worker?

Slide 14

Slide 14 text

An Air Traffic Controller for Your Requests

Slide 15

Slide 15 text

The Life of a Service Worker No Service Worker install Event ↪ Cache the App Shell!

Slide 16

Slide 16 text

GET /shell

Slide 17

Slide 17 text

template placeholder Service Worker Installation site-wide styles Contents of /shell site-wide JS /* inline styles */ </body> Shell

Slide 18

Slide 18 text

The Life of a Service Worker No Service Worker install Event activate Event Idle fetch Event ↪ Cache Clean Up ↪ Handle Network Requests Stopped Stopped

Slide 19

Slide 19 text

Service Worker fetch Interception GET /guide/456 fetch Event /shell (from cache) Shell

Slide 20

Slide 20 text

Service Workers without the Work sw-precache Shell sw-toolbox Content

Slide 21

Slide 21 text

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

Slide 22

Slide 22 text

sw-precache for Your App Shell sw-precache + = github.com/GoogleChrome/sw-precache npm install --save-dev sw-precache Shell

Slide 23

Slide 23 text

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

Slide 24

Slide 24 text

sw-precache in Action: Updates Shell // [file, hash] pairs ... [js/app.js, hashXYZ] ... [styles/all.css, hash789] // Service worker code service-worker.js

Slide 25

Slide 25 text

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.

Slide 26

Slide 26 text

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`], });

Slide 27

Slide 27 text

sw-toolbox for Your Dynamic Content sw-toolbox github.com/GoogleChrome/sw-toolbox npm install --save-dev sw-toolbox Content

Slide 28

Slide 28 text

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

Slide 29

Slide 29 text

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

Slide 30

Slide 30 text

Strategy: Cache/Network Race Content toolbox.fastest

Slide 31

Slide 31 text

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

Slide 32

Slide 32 text

Why use sw-toolbox?

Slide 33

Slide 33 text

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

Slide 34

Slide 34 text

Rein in Your Caches! Content toolbox.router.get( '/path/to/images/.*', toolbox.cacheFirst, {cache: { name: 'images', maxEntries: 6 }} );

Slide 35

Slide 35 text

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$/ });

Slide 36

Slide 36 text

if (‘serviceWorker’ in navigator) { navigator.serviceWorker.register(‘sw.js’); } else { // But not all browsers // support service workers! }

Slide 37

Slide 37 text

Air Traffic Controllers as Progressive Enhancement(?!?)

Slide 38

Slide 38 text

Initial Visit

Slide 39

Slide 39 text

Next Visit: Service Worker Supported

Slide 40

Slide 40 text

Next Visit: Service Worker Not Supported

Slide 41

Slide 41 text

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!

Slide 42

Slide 42 text

Service Workers FTW! But, service workers let you: ✓ Serve the HTML for the landing page cache-first... ✓ ...even if that page is server-rendered.

Slide 43

Slide 43 text

Next Steps:

Slide 44

Slide 44 text

Embrace Your Shell!

Slide 45

Slide 45 text

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

Slide 46

Slide 46 text

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

Slide 47

Slide 47 text

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

Slide 48

Slide 48 text

github.com/Google/web-starter-kit

Slide 49

Slide 49 text

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

Slide 50

Slide 50 text

Instant Loading with Service Workers Jeff Posnick @jeffposnick

Slide 51

Slide 51 text

No content