Skip to content

Instantly share code, notes, and snippets.

@PerpetualBeta PerpetualBeta/sw.js
Created Jun 11, 2017

Embed
What would you like to do?
Perpetual βeta Service Worker
'use strict';
const version = 'v1.17l::';
const staticCacheName = version + 'pwa';
const pagesCacheName = version + 'pages';
const imagesCacheName = version + 'assets';
const offlinePage = '/local-offline.html';
const weblogSlug = '/weblog/';
const cacheList = [
staticCacheName,
pagesCacheName,
imagesCacheName
];
const offlinePages = [
'/',
'/colophon.html',
'/privacy-policy.html',
];
function updateStaticCache() {
return caches.open(staticCacheName)
.then( cache => {
// These items won't block the installation of the Service Worker
cache.addAll([
// images for colophom
'/assets/images/80/892245ca8c69b44ba4d0712e6b96990e.jpg',
'/assets/images/480/892245ca8c69b44ba4d0712e6b96990e.jpg',
'/assets/images/768/892245ca8c69b44ba4d0712e6b96990e.jpg',
'/assets/images/820/892245ca8c69b44ba4d0712e6b96990e.jpg',
'/assets/images/1024/892245ca8c69b44ba4d0712e6b96990e.jpg',
'/assets/images/1640/892245ca8c69b44ba4d0712e6b96990e.jpg',
'/assets/images/80/signature.png',
'/assets/images/480/signature.png',
'/assets/images/80/jonathan_hollin.jpg',
'/assets/images/480/jonathan_hollin.jpg',
//end
'/assets/images/securityheaders.io.svg',
'/assets/js/lunr.min.js',
// '/search-corpus.json',
'/assets/images/workspace_1024.jpg',
'/assets/images/pattern_pixels.png',
].concat(offlinePages));
// These items must be cached for the Service Worker to complete installation
return cache.addAll([
'/assets/css/e09a19bdbd9b236de74c79de99fd3b2f.css',
'/assets/js/965f93b582de716f8fffa227f7562991.js',
// image for offline page
'/assets/images/80/1a0b7891f4d66964a2b75841a0dfd6eb.jpg',
'/assets/images/480/1a0b7891f4d66964a2b75841a0dfd6eb.jpg',
'/assets/images/768/1a0b7891f4d66964a2b75841a0dfd6eb.jpg',
'/assets/images/820/1a0b7891f4d66964a2b75841a0dfd6eb.jpg',
'/assets/images/1024/1a0b7891f4d66964a2b75841a0dfd6eb.jpg',
'/assets/images/1280/1a0b7891f4d66964a2b75841a0dfd6eb.jpg',
'/assets/images/1640/1a0b7891f4d66964a2b75841a0dfd6eb.jpg',
// end
'/assets/js/turbolinks.min.js',
'/assets/js/stackblur.min.js',
'/local-offline.html',
]);
});
}
var exclusions = [
'camera-roll',
'toscani.css',
];
function stashInCache(cacheName, request, response) {
caches.open(cacheName)
.then(cache => {
cache.put(request, response)
});
}
// Limit the number of items in a specified cache.
function trimCache(cacheName, maxItems) {
caches.open(cacheName)
.then( cache => {
cache.keys()
.then(keys => {
if (keys.length > maxItems) {
cache.delete(keys[0])
.then(trimCache(cacheName, maxItems));
}
});
});
}
// Remove caches whose name is no longer valid
function clearOldCaches() {
return caches.keys()
.then( keys => {
return Promise.all(keys
.filter(key => !cacheList.includes(key))
.map(key => caches.delete(key))
);
});
}
self.addEventListener('install', event => {
event.waitUntil(
updateStaticCache()
.then( () => self.skipWaiting() )
);
});
self.addEventListener('activate', event => {
event.waitUntil(
clearOldCaches()
.then( () => self.clients.claim() )
);
});
self.addEventListener('message', event => {
if (event.data.command == 'trimCaches') {
trimCache(pagesCacheName, 50);
trimCache(imagesCacheName, 100);
}
});
self.addEventListener('fetch', event => {
let request = event.request;
let url = new URL(request.url);
// Ignore exclusions
for (var i = 0; i < exclusions.length; i ++) {
if (request.url.indexOf(exclusions[i]) > -1) {
return
}
}
// Ignore non-GET requests
if (request.method !== 'GET') {
return;
}
// For HTML requests, try the network first, fall back to the cache, finally the offline page
if (request.headers.get('Accept').includes('text/html')) {
event.respondWith(
fetch(request)
.then(response => {
// NETWORK
// Stash a copy of this page in the pages cache
let copy = response.clone();
if (offlinePages.includes(url.pathname)) {
stashInCache(staticCacheName, request, copy);
} else {
stashInCache(pagesCacheName, request, copy);
}
return response;
})
.catch( () => {
// CACHE or FALLBACK
return caches.match(request)
.then( response => response || caches.match(offlinePage) );
})
);
return;
}
// For non-HTML requests, look in the cache first, fall back to the network
event.respondWith(
caches.match(request)
.then(response => {
// CACHE
return response || fetch(request)
.then( response => {
// NETWORK
// If the request is for an image, stash a copy of this image in the images cache
if (request.headers.get('Accept').includes('image')) {
let copy = response.clone();
stashInCache(imagesCacheName, request, copy);
}
return response;
})
.catch( () => {
// OFFLINE
// If the request is for an image, show an offline placeholder
if (request.headers.get('Accept').includes('image')) {
return new Response('<svg role="img" aria-labelledby="offline-title" viewBox="0 0 400 300" xmlns="http://www.w3.org/2000/svg"><title id="offline-title">Offline</title><g fill="none" fill-rule="evenodd"><path fill="#D8D8D8" d="M0 0h400v300H0z"/><text fill="#9B9B9B" font-family="Helvetica Neue,Arial,Helvetica,sans-serif" font-size="72" font-weight="bold"><tspan x="93" y="172">offline</tspan></text></g></svg>', {headers: {'Content-Type': 'image/svg+xml', 'Cache-Control': 'no-store'}});
}
});
})
);
});
self.addEventListener('message', function(event) {
caches.open(pagesCacheName).then(function(cache) {
return cache.keys().then(function(requests) {
var urls = requests.filter(function(request){
return request.url.indexOf(weblogSlug) !== -1;
}).map(function(request) {
return request.url;
});
return urls.sort();
}).then(function(urls) {
event.ports[0].postMessage(urls);
});
});
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.