REAL WORLD LESSONS IN PROGRESSIVE WEB APPLICATION/SERVICE WORKER CACHING How Developers Can Build Web Sites With Native App User Experience and the Natural Advantages the Web Offers Businesses and Customers
Apr 08, 2017
REAL WORLD LESSONS IN PROGRESSIVE WEB APPLICATION/SERVICE WORKER CACHINGHow Developers Can Build Web Sites With Native App User Experience and the Natural Advantages the Web Offers Businesses and Customers
RESOURCES
Slide URL slideshare – https://slideshare.com/docluv
Source Code – https://github.com/docluv
PROGRESSIVE WEB APPLICATION COURSE
VideosE-bookChecklistsReference Source CodeBuild Scripts
$97LimitedTime!
Presentation Title Can Be Placed Here 6
PUBLIC LOGO
We Made a PWA Logo Creative Common License! https://github.com/docluv/pwa-logo
Presentation Title Can Be Placed Here 7
LIFE CYCLE
SERVICE WORKER
Presentation Title Can Be Placed Here 8
LIFE CYCLE Lives Separate From Page Must Register Service Worker The Service Worker is Installed It is not Immediately Active
Can be Forced Active Upon Install Activated After All Current References Terminated Now Controls All New Instances of Site
Web Server
Web Page
Service Worker
Cache
2
1
Web Server
Web Page
Service Worker
Cache
2
Presentation Title Can Be Placed Here 12
REGISTRATIONif ('serviceWorker' in navigator) { navigator.serviceWorker.register('/sw.js')
.then(function(registration) { // Registration was successful })
.catch(function(err) { // registration failed :( }); }
Presentation Title Can Be Placed Here 13
INSTALL
self.addEventListener('install', function (e) {
//do something
});
Presentation Title Can Be Placed Here 14
ACTIVATE
self.addEventListener('activate', function (event) { console.log('Service Worker activating.');});
Presentation Title Can Be Placed Here 15
ACTIVATEself.addEventListener('install', function (e) {
e.waitUntil(…})); self.skipWaiting();});
THE PROXY SERVER IN YOUR POCKET
SERVICE WORKER
Presentation Title Can Be Placed Here 18
CLASSIC WEB CLIENT-SERVER
Web Server
Web Page
Presentation Title Can Be Placed Here 19
ADD SERVICE WORKER
Web ServerWeb Page
Service Worker
Presentation Title Can Be Placed Here 20
Web ServerWeb
Page
Service Worker
Presentation Title Can Be Placed Here 21
Web ServerWeb
Page
Service Worker
Cache
Presentation Title Can Be Placed Here 22
SERVICE WORKER CACHE
Persist Files with Response HeadersLimited by Device ResourcesAvailable Online & Offline
Presentation Title Can Be Placed Here 23
self.addEventListener('install', function (e) {
e.waitUntil( caches.open(cacheName).then(function (cache) {
return cache.addAll(filesToCache).catch(function (error) { console.log(error);
}); }) );});
Presentation Title Can Be Placed Here 24
self.addEventListener('fetch', function (event) {
//intercept fetch request (any request from the UI thread for a file or API) and return from cache or get from server & cache it event.respondWith(
caches.match(event.request).then(function (resp) {
return resp || fetchAsset(event);
})
);
});
Web ServerWeb
Page
Service Worker
CacheIndexDB
Presentation Title Can Be Placed Here 26
THE CACHE STRATEGIES
SERVICE WORKER
Web Page
Service Worker
Web Page
Service Worker
Cache
Presentation Title Can Be Placed Here 29
OFFLINE COOKBOOK
JAKE ARCHIBALDChrome Team
https://jakearchibald.com/2014/offline-cookbook/
self.addEventListener('install', function(event) { event.waitUntil( caches.open('mysite-static-
v3').then(function(cache) {
return cache.addAll([ '/css/whatever-v3.css',
'/css/imgs/sprites-v6.png', '/css/fonts/whatever-v8.woff', '/js/all-min-v4.js' // etc
]); }) ); });
self.addEventListener('install', function(event) { event.waitUntil(
caches.open('mygame-core-v1').then(function(cache) {
cache.addAll( // levels 11-20 ); return cache.addAll(
// core assets & levels 1-10 ); })
); });
self.addEventListener('activate', function(event) { event.waitUntil( caches.keys()
.then(function(cacheNames) { return Promise.all(
cacheNames.filter(function(cacheName) { // Return true if you want to remove this cache, // but remember that caches are shared across // the whole origin })
.map(function(cacheName) { return caches.delete(cacheName);
}) );
}) );
});
document.querySelector('.cache-article').addEventListener('click', function(event) {
event.preventDefault(); var id = this.dataset.articleId; caches.open('mysite-article-' + id)
.then(function(cache) { fetch('/get-article-urls?id=' +
id).then(function(response) { response.json();
}).then(function(urls) { cache.addAll(urls); });
}); });
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;
}); });
}) );
});
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;
}) }) ); });
self.addEventListener('install', function(event) { event.waitUntil( caches.open('mysite-static-
v3').then(function(cache) {
return cache.addAll([ '/css/whatever-v3.css',
'/css/imgs/sprites-v6.png', '/css/fonts/whatever-v8.woff', '/js/all-min-v4.js' // etc
]); }) ); });
self.addEventListener('fetch', function(event) { // If a match isn't found in the cache, the
response // will look like a connection error
event.respondWith(caches.match(event.request)); });
self.addEventListener('fetch', function(event) { event.respondWith(fetch(event.request));
// or simply don't call event.respondWith, which
// will result in default browser behavior });
self.addEventListener('fetch', function(event) { event.respondWith( caches.match(event.request)
.then(function(response) { return response ||
fetch(event.request); })
); });
self.addEventListener('fetch', function(event) { event.respondWith(
promiseAny([ caches.match(event.request),
fetch(event.request) ])
); });
self.addEventListener('fetch', function(event) { event.respondWith( fetch(event.request).catch(
function() { return caches.match(event.request); })
); });
self.addEventListener('fetch', function(event) {event.respondWith(
caches.open('mysite-dynamic').then(function(cache) {
return fetch(event.request).then(function(response) {
cache.put(event.request, response.clone());
return response; });
}) );
});
self.addEventListener('fetch', function(event) {
event.respondWith(caches.match(event.request)
.then(function(response) { return response ||
fetch(event.request);}).catch(function() {
return caches.match('/offline.html');
}) );
});
CACHE TOOLS
SERVICE WORKER
Presentation Title Can Be Placed Here 62
SERVICE WORKER TOOLS
sw_precache A node module to generate service worker code that
will precache specific resources so they work offline. https://github.com/googlechrome/sw-precache
sw_toolbox A collection of service worker tools for offlining
runtime requests https://github.com/GoogleChrome/sw-toolbox