the gotchas in your path to production.
@GatMesquer
MrFrontend Β Β
"53% of mobile site visits are abandoned if pages take longer than 3 seconds to load."
- Alex Shellhammer, Double click
3s network round-trip on average 2G
(bit.ly/network-costs)
320ms to load 1MB
(bit.ly/network-costs)
"Used correctly, caching is a massive performance enhancement and bandwidth saver"
- Jake Archibald, dev advocate for Google Chrome
"Used correctly, caching is a massive performance enhancement and bandwidth saver"
- Jake Archibald, dev advocate for Google Chrome
Β
The goal is to avoid requesting resources from the network as much as possible.
Browser cache
Browser built in mechanism
πΒ repeat visits
Browser cache
Optimized browser cache
Load resources before they are required
<link rel="import"...>
requestIdleCallback
<script src="~.js"... defer>
Β
Some proactive page load improvements
Browser cache
Optimized browser cache
Content caching
Proactive page load improvements
IndexedDB
Structured Data
Cache Storage
URL addressable
Browser cache
Optimized browser cache
π Service Workers + Cache Storage
Content caching
Full cache control
Proactive page load improvements
+ Offline available
Browser cache
π
ππ
ππππ
Optimized browser cache
Content caching
Full cache control
0
Browser cache
π
Optimized browser cache
Content caching
Full cache control
0
Unpredictable
~ Content predictability
Fully predictable
ππ
ππππ
Browser cache
π
Optimized browser cache
Content caching
Full cache control
0
Unpredictable
~ Content predictability
Fully predictable
Coarse granularity
~ Content granularity
Content granularity
ππ
ππππ
Browser cache
π
Optimized browser cache
Content caching
Full cache control
0
Unpredictable
~ Content predictability
Fully predictable
Coarse granularity
~ Content granularity
Content granularity
Network response only
All response types
ππ
ππππ
Browser cache
π
Optimized browser cache
Content caching
Full cache control
0
Unpredictable
~ Content predictability
Fully predictable
Coarse granularity
~ Content granularity
Content granularity
Network response only
All response types
Best return on your time invested
ππ
ππππ
How much space do we get ?
50 MB of persistent storage on all devices and browsers
chrome dev summit 2016
How reliable is it ?
chrome dev summit 2016
What is coming ?
chrome dev summit 2016
Cache-Control: max-age=31536000, immutable
The content for an specific URL never changes
<script src="/script-v1.js"></script>
<link rel="stylesheet" href="/styles-Fs837mq1c.css">
<img src="/img/banner-02-01-2017.jpg" alt="β¦">
Cache-Control: max-age=31536000, immutable
Use the immutable Cache-Control extension.
Β
Β
Cache-Control: max-age=31536000, immutable
"This change effectively eliminated revalidation requests to us from up-to-date versions of Firefox which, in many cases, can improve load times by seconds"
- Nathan Schloss, Software Engineer, Facebook
- Does not work with often updated content with a fixed URL (blog posts, articles, ...)
Cache-Control: no-cache
The content for an specific URL may change so it always must be revalidated with the server.
Important notes:
doesn't mean | it means | |
---|---|---|
no-cache | don't cache | must be revalidated with the server before using a cached version |
no-store | can not be cached at all | |
must-revalidate | must revalidate | the cached version can be used if it's younger than the provided max-age, otherwise revalidate |
Important notes:
no-cache !== max-age=0
Β
no-cache: the browser MUST revalidate with the server before using a cached copy.
Β
max-age=0: the time of the cache expired so the browser SHOULD (but might not) revalidate with the server before using a cached copy.
- Requires always a network fetch for each resource.
Remember:
Β
Remember:
Lifecycle events:
<script>
'use strict';
self.addEventListener('install', function(event) {
console.log('install');
});
self.addEventListener('activate', function(event) {
console.log('activate');
});
self.addEventListener('fetch', function(event) {
console.log('fetch:', event.request.url);
});
</script>
jakearchibald.com
Ideal for: all the static files for this version.
jakearchibald.com
Ideal for: bigger resources that are not needed straight away.
Ideal for: not reloading from the network static assets.
Work together
Ideal for: want to be sure to fetch the most fresh data and we don't mind the network overload.
Cache busting in the Service Worker
let request = new Request(url, {cache: 'no-cache'});
jakearchibald.com
Ideal for: Clean-up & migration.
Nicolas Hoizey
jakearchibald.com
Ideal for: let the user pick what should be available offline.
Ideal for: reuse cached resources managed by someone else.
Is possible to share resources that were cached Β by another service worker or script.
jakearchibald.com
Ideal for: frequently updated resources.
jakearchibald.com
Ideal for: frequently updated resources.
<script>
self.addEventListener('fetch', function(event) {
event.respondWith(
caches.open('mysite-dynamic').then(function(cache) {
return cache.match(event.request).then(function (response) {
return response || fetch(event.request).then(function(response) {
cache.put(event.request, response.clone());
return response;
});
});
})
);
});
</script>
jakearchibald.com
Ideal for: frequently updated resources when having the latest version is non-essential.
jakearchibald.com
Ideal for: frequently updated resources when having the latest version is non-essential.
self.addEventListener('fetch', function(event) {
event.respondWith(
caches.open('mysite-dynamic').then(function(cache) {
return cache.match(event.request).then(function(response) {
var fetchPromise = fetch(event.request).then(function(networkResponse) {
cache.put(event.request, networkResponse.clone());
return networkResponse;
})
return response || fetchPromise;
})
})
);
});
jakearchibald.com
Ideal for: content related to a notification.
jakearchibald.com
Ideal for: content related to a notification.
self.addEventListener('push', function(event) {
if (event.data.text() == 'new-email') {
event.waitUntil(
caches.open('mysite-dynamic').then(function(cache) {
return fetch('/inbox.json').then(function(response) {
cache.put('/inbox.json', response.clone());
return response.json();
});
}).then(function(emails) {
registration.showNotification("New email", {
body: "From " + emails[0].from.name
tag: "new-email"
});
})
);
}
});
self.addEventListener('notificationclick', function(event) {
if (event.notification.tag == 'new-email') {
new WindowClient('/inbox/');
}
});
jakearchibald.com
Ideal for: non urgent updates.
self.addEventListener('sync', function(event) {
if (event.id == 'update-leaderboard') {
event.waitUntil(
caches.open('mygame-dynamic').then(function(cache) {
return cache.add('/leaderboard.json');
})
);
}
});
jakearchibald.com
Ideal for: common requests for offline-first.
self.addEventListener('fetch', function(event) {
event.respondWith(
caches.match(event.request).then(function(response) {
return response || fetch(event.request);
})
);
});
jakearchibald.com
Ideal for: quick fix for frequently updated resources when offline
self.addEventListener('fetch', function(event) {
event.respondWith(
fetch(event.request).catch(function() {
return caches.match(event.request);
})
);
});
jakearchibald.com
Ideal for:Β consistent generic fallback for not found resources.
Cache-Control: max-age=31536000, immutable
For your service-worker.js file !!!
Cache-Control: max-age=31536000, immutable
For your service-worker.js file !!!
Service Workers must be downloaded after 24 hours of the first download.
Follow
Β
Libraries
@GatMesquer
MrFrontend Β Β
β€οΈΒ Margherita Farina