service workers for performance

64
Service Workers The Practical Bits @patmeenan Patrick Meenan

Upload: patrick-meenan

Post on 07-Aug-2015

2.802 views

Category:

Technology


3 download

TRANSCRIPT

Page 1: Service Workers for Performance

Service Workers

The Practical Bits

@patmeenan

Patrick Meenan

Page 2: Service Workers for Performance

Slides

Slideshare: http://www.slideshare.net/patrickmeenan

Twitter: @patmeenan (and to #velocityconf)

Velocity Site, attached to session information

Video: https://www.youtube.com/user/patmeenan

Office Hours:  Friday, May 29 from 12:30pm-1:00pm@patmeenan

Page 3: Service Workers for Performance

Chrome Team @Google (performance)

WebPageTest

[email protected]

@patmeenan

Page 4: Service Workers for Performance

The Real Experts

Alex Russell@slightlylate

Jake Archibald@jaffathecake

Page 5: Service Workers for Performance

Service Workers

Page 6: Service Workers for Performance

DOM

Resource Fetching in Chrome

Page 7: Service Workers for Performance

DOM

Resource Fetching in Chrome

In-memory Resource

Cache

Page 8: Service Workers for Performance

DOM

Resource Fetching in Chrome

In-memory Resource

Cache

Resource Fetcher

Page 9: Service Workers for Performance

DOM

Resource Fetching in Chrome

Resource Fetcher

Net Stack

Page 10: Service Workers for Performance

DOM

Resource Fetching in Chrome

In-memory Resource

Cache

Resource Fetcher

Net Stack

Disk Cache

Page 11: Service Workers for Performance

DOM

Resource Fetching in Chrome

In-memory Resource

Cache

Resource Fetcher

Net Stack Net

Disk Cache

Page 12: Service Workers for Performance

DOM

Resource Fetching in Chrome

In-memory Resource

Cache

Resource Fetcher

Net Stack Net

Disk Cache

Service Worker

SW Added and Removed

Here!

Page 13: Service Workers for Performance

CapabilitiesSees every request for your document

- Including cross-origin

- And headersCan synthesize responsesSupports fetchHas a programmable cache and Indexed DB

Page 14: Service Workers for Performance

LimitationsHTTPS documents onlyNot active for first viewiFrames are separate documentsNon-CORS Cross-origin responses are opaqueNo global state

- or concept of a “page”No Sync API’s (localstorage, XHR, etc)

Page 15: Service Workers for Performance

http://memegenerator.net/instance/62336209

Page 16: Service Workers for Performance

Registering

if ('serviceWorker' in navigator) {

navigator.serviceWorker.register('/my-app/sw.js', {

scope: '/my-app/'

});

}

https://github.com/slightlyoff/ServiceWorker/blob/master/explainer.md

Page 17: Service Workers for Performance

Registering

if ('serviceWorker' in navigator) {

navigator.serviceWorker.register('/my-app/sw.js', {

scope: '/my-app/'

});

}

https://github.com/slightlyoff/ServiceWorker/blob/master/explainer.md

Page 18: Service Workers for Performance

Registering

if ('serviceWorker' in navigator) {

navigator.serviceWorker.register('/my-app/sw.js', {

scope: '/my-app/'

});

}

https://github.com/slightlyoff/ServiceWorker/blob/master/explainer.md

Page 19: Service Workers for Performance

Registering

if ('serviceWorker' in navigator) {

navigator.serviceWorker.register('/my-app/sw.js', {

scope: '/my-app/'

});

}

https://github.com/slightlyoff/ServiceWorker/blob/master/explainer.md

Page 20: Service Workers for Performance

Install / activateself.addEventListener('install', function(event) {

event.waitUntil(

fetchStuffAndInitDatabases()

);

});

self.addEventListener('activate', function(event) {

// You're good to go!

});

https://github.com/slightlyoff/ServiceWorker/blob/master/explainer.md

Page 21: Service Workers for Performance

Network Intercepting

self.addEventListener('fetch', function(event) {

event.respondWith(new Response("Hello world!"));

});

https://github.com/slightlyoff/ServiceWorker/blob/master/explainer.md

Page 22: Service Workers for Performance

Enough Theory – Let’s Use It

Page 23: Service Workers for Performance

Offline Content

Most benefit for Single-Page Apps where app/data are separated

Service Workers become progressive enhancement for offline support

Page 24: Service Workers for Performance

Offline Content

Pre-cache offline content

Pass live requests through when online

- Caching the responses

Serve cached responses when offline (if available)

Serve offline-specific versions otherwise

Page 25: Service Workers for Performance

Offline Content – Pre-caching

self.addEventListener( ‘install’, function(event) {

event.waitUntil(

caches.open(‘my-offline-cache-v1’).then( function(cache) {

return cache.addAll([

‘/site.js’,

‘/images/offline.png’,

‘/offline.html’]);

}));});

Page 26: Service Workers for Performance

Offline Content – Pre-caching

self.addEventListener( ‘install’, function(event) {

event.waitUntil(

caches.open(‘my-offline-cache-v1’).then( function(cache) {

return cache.addAll([

‘/site.js’,

‘/images/offline.png’,

‘/offline.html’]);

}));});

Page 27: Service Workers for Performance

Offline Content – Pre-caching

self.addEventListener( ‘install’, function(event) {

event.waitUntil(

caches.open(‘my-offline-cache-v1’).then( function(cache) {

return cache.addAll([

‘/site.js’,

‘/images/offline.png’,

‘/offline.html’]);

}));});

Page 28: Service Workers for Performance

Offline Content – Pre-caching

self.addEventListener( ‘install’, function(event) {

event.waitUntil(

caches.open(‘my-offline-cache-v1’).then( function(cache) {

return cache.addAll([

‘/site.js’,

‘/images/offline.png’,

‘/offline.html’]);

}));});

Page 29: Service Workers for Performance

Offline Content – Pre-caching

self.addEventListener( ‘install’, function(event) {

event.waitUntil(

caches.open(‘my-offline-cache-v1’).then( function(cache) {

return cache.addAll([

‘/site.js’,

‘/images/offline.png’,

‘/offline.html’]);

}));});

Page 30: Service Workers for Performance

Offline Content – Fetch Processing

self.addEventListener( 'fetch', function(event) {

if (navigator.online) {

event.respondWith( onlineRequest(event.request) );

} else {

event.respondWith( offlineRequest(event.request) );

}

});

Page 31: Service Workers for Performance

Offline Content – Fetch Processing

self.addEventListener( 'fetch', function(event) {

if (navigator.online) {

event.respondWith( onlineRequest(event.request) );

} else {

event.respondWith( offlineRequest(event.request) );

}

});

Page 32: Service Workers for Performance

Offline Content – Fetch Processing

self.addEventListener( 'fetch', function(event) {

if (navigator.online) {

event.respondWith( onlineRequest(event.request) );

} else {

event.respondWith( offlineRequest(event.request) );

}

});

Page 33: Service Workers for Performance

Offline Content – Fetch Processing

self.addEventListener( 'fetch', function(event) {

if (navigator.online) {

event.respondWith( onlineRequest(event.request) );

} else {

event.respondWith( offlineRequest(event.request) );

}

});

Page 34: Service Workers for Performance

Offline Content – Fetch Processing

self.addEventListener( 'fetch', function(event) {

if (navigator.online) {

event.respondWith( onlineRequest(event.request) );

} else {

event.respondWith( offlineRequest(event.request) );

}

});

Page 35: Service Workers for Performance

Offline Content – Online Response

function onlineRequest(request) {

return caches.match(request)

.then(function(response) {

}

);

}

Page 36: Service Workers for Performance

Offline Content – Online Response

function onlineRequest(request) {

return caches.match(request).then(function(response) {

if (response) {

return response;

} else {

return fetch(request);

}

});

}

Page 37: Service Workers for Performance

Offline Content – Online Response

function onlineRequest(request) {

return caches.match(request).then(function(response) {

if (response) {

return response;

} else {

return fetch(request);

}

});

}

Page 38: Service Workers for Performance

Offline Content – Online Response…

var fetchRequest = request.clone();

return fetch(fetchRequest).then( function(response) {

var responseToCache = response.clone();

caches.open(CACHE_NAME).then( function(cache) {

cache.put(request, responseToCache);

});

return response;

});

Page 39: Service Workers for Performance

Offline Content – Online Response…

var fetchRequest = request.clone();

return fetch(fetchRequest).then( function(response) {

var responseToCache = response.clone();

caches.open(CACHE_NAME).then( function(cache) {

cache.put(request, responseToCache);

});

return response;

});

Page 40: Service Workers for Performance

Offline Content – Online Response…

var fetchRequest = request.clone();

return fetch(fetchRequest).then( function(response) {

var responseToCache = response.clone();

caches.open(CACHE_NAME).then( function(cache) {

cache.put(request, responseToCache);

});

return response;

});

Page 41: Service Workers for Performance

Offline Content – Online Response…

var fetchRequest = request.clone();

return fetch(fetchRequest).then( function(response) {

var responseToCache = response.clone();

caches.open(CACHE_NAME).then( function(cache) {

cache.put(request, responseToCache);

});

return response;

});

Page 42: Service Workers for Performance

Offline Content – Online Response…

var fetchRequest = request.clone();

return fetch(fetchRequest).then( function(response) {

var responseToCache = response.clone();

caches.open(CACHE_NAME).then( function(cache) {

cache.put(request, responseToCache);

});

return response;

});

Page 43: Service Workers for Performance

Offline Content – Online Response…

var fetchRequest = request.clone();

return fetch(fetchRequest).then( function(response) {

var responseToCache = response.clone();

caches.open(CACHE_NAME).then( function(cache) {

cache.put(request, responseToCache);

});

return response;

});

Page 44: Service Workers for Performance

Offline Content – Offline Response

function offlineRequest(request) {

if (request.url.match(/\.png$/)) {

return caches.match(‘/images/offline.png’);

} else if (request.url.match(/\.html$/)) {

return caches.match(‘/offline.html’);

}

}

Page 45: Service Workers for Performance

Offline Content – Offline Response

function offlineRequest(request) {

if (request.url.match(/\.png$/)) {

return caches.match(‘/images/offline.png’);

} else if (request.url.match(/\.html$/)) {

return caches.match(‘/offline.html’);

}

}

Page 46: Service Workers for Performance

Other Uses

Not limited to applications designed for offline/SPALegacy apps + fetch intercept = Awesome possibilities

Page 47: Service Workers for Performance

Custom Error Pages

Fetch Request NormallyFor non-200 responses serve a local error pageNot just server errors:

- DNS failures

- CDN/Proxy Errors

- Intermediaries

Page 48: Service Workers for Performance

SPOF Prevention

Identify requests of interest

- 3rd-party javascript

- FontsSet a timerPass fetch requests through If timer expires before fetch completes generate error response

Page 49: Service Workers for Performance

CDN/Origin Failover

Identify CDN requests by URLSet a timerPass fetch request through If timer expires, create fetch request to originRespond with first fetch request to complete

Page 50: Service Workers for Performance

Multi-Origin/CDN

Identify CDN requests by URLReplace CDN domain with alternate CDN (or origin)Keep track of performance by originPrefer faster origin (keep measuring)

Could also race the CDNs in parallel

- Be careful about increased data

Page 51: Service Workers for Performance

Stale-While-Revalidate

Respond with local cached resource

- Ignoring Expires, max-age, etc.Pass fetch request through in parallelUpdate cache with new response

Works best for known resources (analytics/ads JS, etc)

Page 52: Service Workers for Performance

Prefetch

Custom response headers with prefetch resourcesWhen idle, prefetch suggested resources

Page 53: Service Workers for Performance

Resource Prioritization/Scheduling

Track in-flight requestsMake scheduling decisions as new requests come inCustom application-aware scheduling logic

- Delay JS if it is known to be at the end

- Delay footer images

- etc

Page 54: Service Workers for Performance

Delta CompressionDelta compression for build->build updates

- Include version in URL scheme

- Get latest version number from cache

- Request delta from server

- Apply patch

- Cache new version

New compression algorithms

Page 55: Service Workers for Performance

Custom CompressionNew compression algorithms

- Brotli

- Fractal image compression

- JSON-specific dictionaries

- Application-specificProve-out new algorithms before standardizing…as long as it can be implemented in JS and code size is

reasonable

Page 56: Service Workers for Performance

Incremental Progressive Images

Identify JPEG image requests from known originSynthesize responseRange request (or smarter) for first few scansStream initial range into synthesized responseRange request for remaining image (some point later)Append remaining data into synthesized response

Page 57: Service Workers for Performance

Drawing Images Locally

930 x 11,362 px WebPageTest waterfall

351KB compressed PNG

42 MB in-memory (server) to generate

< 20KB compressed JSON data to describe

Prefer actual images for WPT waterfalls for easier embedding

- Otherwise SVG, Canvas or DOM would work

Page 58: Service Workers for Performance

Drawing Images Locally*

Identify appropriate requests (i.e. waterfall.png?...)Fetch data necessary to draw imageDraw to canvasExtract as PNGSynthesize PNG response

* Work in progress, coming soon

Page 59: Service Workers for Performance

Metrics/Debugging

Pass all requests throughPassively observe timings and successReport metrics backGives visibility into failures and requests that are in flight

- Unlike resource timing

Page 60: Service Workers for Performance

And there’s more…

Page 61: Service Workers for Performance

Required for…Push Notifications

- https://gauntface.com/blog/2014/12/15/push-notifications-service-worker

Background Sync- https://github.com/slightlyoff/BackgroundSync/blob/master/explainer.md

GeoFencing- https://github.com/slightlyoff/Geofencing

Page 62: Service Workers for Performance

AvailabilityChrome Stable (40+)Opera (27+)Firefox (Nightly)

Page 63: Service Workers for Performance

Composable

Service workers can “importScripts”Begging for a framework to handle pluggable pipeline

- With compatible plugins for processing

- Delta compression + scheduling + Stale While Revalidate…

- Just a matter of importing the libs

Page 64: Service Workers for Performance

Thank You!

@patmeenan

[email protected]