service workers for performance
TRANSCRIPT
![Page 1: Service Workers for Performance](https://reader036.vdocument.in/reader036/viewer/2022062406/55c48dcebb61ebd7528b4602/html5/thumbnails/1.jpg)
Service Workers
The Practical Bits
@patmeenan
Patrick Meenan
![Page 2: Service Workers for Performance](https://reader036.vdocument.in/reader036/viewer/2022062406/55c48dcebb61ebd7528b4602/html5/thumbnails/2.jpg)
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 4: Service Workers for Performance](https://reader036.vdocument.in/reader036/viewer/2022062406/55c48dcebb61ebd7528b4602/html5/thumbnails/4.jpg)
The Real Experts
Alex Russell@slightlylate
Jake Archibald@jaffathecake
![Page 5: Service Workers for Performance](https://reader036.vdocument.in/reader036/viewer/2022062406/55c48dcebb61ebd7528b4602/html5/thumbnails/5.jpg)
Service Workers
![Page 6: Service Workers for Performance](https://reader036.vdocument.in/reader036/viewer/2022062406/55c48dcebb61ebd7528b4602/html5/thumbnails/6.jpg)
DOM
Resource Fetching in Chrome
![Page 7: Service Workers for Performance](https://reader036.vdocument.in/reader036/viewer/2022062406/55c48dcebb61ebd7528b4602/html5/thumbnails/7.jpg)
DOM
Resource Fetching in Chrome
In-memory Resource
Cache
![Page 8: Service Workers for Performance](https://reader036.vdocument.in/reader036/viewer/2022062406/55c48dcebb61ebd7528b4602/html5/thumbnails/8.jpg)
DOM
Resource Fetching in Chrome
In-memory Resource
Cache
Resource Fetcher
![Page 9: Service Workers for Performance](https://reader036.vdocument.in/reader036/viewer/2022062406/55c48dcebb61ebd7528b4602/html5/thumbnails/9.jpg)
DOM
Resource Fetching in Chrome
Resource Fetcher
Net Stack
![Page 10: Service Workers for Performance](https://reader036.vdocument.in/reader036/viewer/2022062406/55c48dcebb61ebd7528b4602/html5/thumbnails/10.jpg)
DOM
Resource Fetching in Chrome
In-memory Resource
Cache
Resource Fetcher
Net Stack
Disk Cache
![Page 11: Service Workers for Performance](https://reader036.vdocument.in/reader036/viewer/2022062406/55c48dcebb61ebd7528b4602/html5/thumbnails/11.jpg)
DOM
Resource Fetching in Chrome
In-memory Resource
Cache
Resource Fetcher
Net Stack Net
Disk Cache
![Page 12: Service Workers for Performance](https://reader036.vdocument.in/reader036/viewer/2022062406/55c48dcebb61ebd7528b4602/html5/thumbnails/12.jpg)
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](https://reader036.vdocument.in/reader036/viewer/2022062406/55c48dcebb61ebd7528b4602/html5/thumbnails/13.jpg)
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](https://reader036.vdocument.in/reader036/viewer/2022062406/55c48dcebb61ebd7528b4602/html5/thumbnails/14.jpg)
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](https://reader036.vdocument.in/reader036/viewer/2022062406/55c48dcebb61ebd7528b4602/html5/thumbnails/15.jpg)
http://memegenerator.net/instance/62336209
![Page 16: Service Workers for Performance](https://reader036.vdocument.in/reader036/viewer/2022062406/55c48dcebb61ebd7528b4602/html5/thumbnails/16.jpg)
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](https://reader036.vdocument.in/reader036/viewer/2022062406/55c48dcebb61ebd7528b4602/html5/thumbnails/17.jpg)
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](https://reader036.vdocument.in/reader036/viewer/2022062406/55c48dcebb61ebd7528b4602/html5/thumbnails/18.jpg)
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](https://reader036.vdocument.in/reader036/viewer/2022062406/55c48dcebb61ebd7528b4602/html5/thumbnails/19.jpg)
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](https://reader036.vdocument.in/reader036/viewer/2022062406/55c48dcebb61ebd7528b4602/html5/thumbnails/20.jpg)
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](https://reader036.vdocument.in/reader036/viewer/2022062406/55c48dcebb61ebd7528b4602/html5/thumbnails/21.jpg)
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](https://reader036.vdocument.in/reader036/viewer/2022062406/55c48dcebb61ebd7528b4602/html5/thumbnails/22.jpg)
Enough Theory – Let’s Use It
![Page 23: Service Workers for Performance](https://reader036.vdocument.in/reader036/viewer/2022062406/55c48dcebb61ebd7528b4602/html5/thumbnails/23.jpg)
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](https://reader036.vdocument.in/reader036/viewer/2022062406/55c48dcebb61ebd7528b4602/html5/thumbnails/24.jpg)
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](https://reader036.vdocument.in/reader036/viewer/2022062406/55c48dcebb61ebd7528b4602/html5/thumbnails/25.jpg)
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](https://reader036.vdocument.in/reader036/viewer/2022062406/55c48dcebb61ebd7528b4602/html5/thumbnails/26.jpg)
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](https://reader036.vdocument.in/reader036/viewer/2022062406/55c48dcebb61ebd7528b4602/html5/thumbnails/27.jpg)
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](https://reader036.vdocument.in/reader036/viewer/2022062406/55c48dcebb61ebd7528b4602/html5/thumbnails/28.jpg)
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](https://reader036.vdocument.in/reader036/viewer/2022062406/55c48dcebb61ebd7528b4602/html5/thumbnails/29.jpg)
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](https://reader036.vdocument.in/reader036/viewer/2022062406/55c48dcebb61ebd7528b4602/html5/thumbnails/30.jpg)
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](https://reader036.vdocument.in/reader036/viewer/2022062406/55c48dcebb61ebd7528b4602/html5/thumbnails/31.jpg)
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](https://reader036.vdocument.in/reader036/viewer/2022062406/55c48dcebb61ebd7528b4602/html5/thumbnails/32.jpg)
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](https://reader036.vdocument.in/reader036/viewer/2022062406/55c48dcebb61ebd7528b4602/html5/thumbnails/33.jpg)
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](https://reader036.vdocument.in/reader036/viewer/2022062406/55c48dcebb61ebd7528b4602/html5/thumbnails/34.jpg)
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](https://reader036.vdocument.in/reader036/viewer/2022062406/55c48dcebb61ebd7528b4602/html5/thumbnails/35.jpg)
Offline Content – Online Response
function onlineRequest(request) {
return caches.match(request)
.then(function(response) {
…
}
);
}
![Page 36: Service Workers for Performance](https://reader036.vdocument.in/reader036/viewer/2022062406/55c48dcebb61ebd7528b4602/html5/thumbnails/36.jpg)
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](https://reader036.vdocument.in/reader036/viewer/2022062406/55c48dcebb61ebd7528b4602/html5/thumbnails/37.jpg)
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](https://reader036.vdocument.in/reader036/viewer/2022062406/55c48dcebb61ebd7528b4602/html5/thumbnails/38.jpg)
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](https://reader036.vdocument.in/reader036/viewer/2022062406/55c48dcebb61ebd7528b4602/html5/thumbnails/39.jpg)
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](https://reader036.vdocument.in/reader036/viewer/2022062406/55c48dcebb61ebd7528b4602/html5/thumbnails/40.jpg)
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](https://reader036.vdocument.in/reader036/viewer/2022062406/55c48dcebb61ebd7528b4602/html5/thumbnails/41.jpg)
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](https://reader036.vdocument.in/reader036/viewer/2022062406/55c48dcebb61ebd7528b4602/html5/thumbnails/42.jpg)
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](https://reader036.vdocument.in/reader036/viewer/2022062406/55c48dcebb61ebd7528b4602/html5/thumbnails/43.jpg)
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](https://reader036.vdocument.in/reader036/viewer/2022062406/55c48dcebb61ebd7528b4602/html5/thumbnails/44.jpg)
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](https://reader036.vdocument.in/reader036/viewer/2022062406/55c48dcebb61ebd7528b4602/html5/thumbnails/45.jpg)
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](https://reader036.vdocument.in/reader036/viewer/2022062406/55c48dcebb61ebd7528b4602/html5/thumbnails/46.jpg)
Other Uses
Not limited to applications designed for offline/SPALegacy apps + fetch intercept = Awesome possibilities
![Page 47: Service Workers for Performance](https://reader036.vdocument.in/reader036/viewer/2022062406/55c48dcebb61ebd7528b4602/html5/thumbnails/47.jpg)
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](https://reader036.vdocument.in/reader036/viewer/2022062406/55c48dcebb61ebd7528b4602/html5/thumbnails/48.jpg)
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](https://reader036.vdocument.in/reader036/viewer/2022062406/55c48dcebb61ebd7528b4602/html5/thumbnails/49.jpg)
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](https://reader036.vdocument.in/reader036/viewer/2022062406/55c48dcebb61ebd7528b4602/html5/thumbnails/50.jpg)
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](https://reader036.vdocument.in/reader036/viewer/2022062406/55c48dcebb61ebd7528b4602/html5/thumbnails/51.jpg)
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](https://reader036.vdocument.in/reader036/viewer/2022062406/55c48dcebb61ebd7528b4602/html5/thumbnails/52.jpg)
Prefetch
Custom response headers with prefetch resourcesWhen idle, prefetch suggested resources
![Page 53: Service Workers for Performance](https://reader036.vdocument.in/reader036/viewer/2022062406/55c48dcebb61ebd7528b4602/html5/thumbnails/53.jpg)
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](https://reader036.vdocument.in/reader036/viewer/2022062406/55c48dcebb61ebd7528b4602/html5/thumbnails/54.jpg)
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](https://reader036.vdocument.in/reader036/viewer/2022062406/55c48dcebb61ebd7528b4602/html5/thumbnails/55.jpg)
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](https://reader036.vdocument.in/reader036/viewer/2022062406/55c48dcebb61ebd7528b4602/html5/thumbnails/56.jpg)
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](https://reader036.vdocument.in/reader036/viewer/2022062406/55c48dcebb61ebd7528b4602/html5/thumbnails/57.jpg)
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](https://reader036.vdocument.in/reader036/viewer/2022062406/55c48dcebb61ebd7528b4602/html5/thumbnails/58.jpg)
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](https://reader036.vdocument.in/reader036/viewer/2022062406/55c48dcebb61ebd7528b4602/html5/thumbnails/59.jpg)
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](https://reader036.vdocument.in/reader036/viewer/2022062406/55c48dcebb61ebd7528b4602/html5/thumbnails/60.jpg)
And there’s more…
![Page 61: Service Workers for Performance](https://reader036.vdocument.in/reader036/viewer/2022062406/55c48dcebb61ebd7528b4602/html5/thumbnails/61.jpg)
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](https://reader036.vdocument.in/reader036/viewer/2022062406/55c48dcebb61ebd7528b4602/html5/thumbnails/62.jpg)
AvailabilityChrome Stable (40+)Opera (27+)Firefox (Nightly)
![Page 63: Service Workers for Performance](https://reader036.vdocument.in/reader036/viewer/2022062406/55c48dcebb61ebd7528b4602/html5/thumbnails/63.jpg)
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