Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
A basic serviceworker implementation for offline website viewing
// Licensed under a CC0 1.0 Universal (CC0 1.0) Public Domain Dedication
// http://creativecommons.org/publicdomain/zero/1.0/
var version = 'v2.0.24:';
var offlineFundamentals = [
'/',
'/offline/'
];
//Add core website files to cache during serviceworker installation
var updateStaticCache = function() {
return caches.open(version + 'fundamentals').then(function(cache) {
return Promise.all(offlineFundamentals.map(function(value) {
var request = new Request(value);
var url = new URL(request.url);
if (url.origin != location.origin) {
request = new Request(value, {mode: 'no-cors'});
}
return fetch(request).then(function(response) {
var cachedCopy = response.clone();
return cache.put(request, cachedCopy);
});
}))
})
};
//Clear caches with a different version number
var clearOldCaches = function() {
return caches.keys().then(function(keys) {
return Promise.all(
keys
.filter(function (key) {
return key.indexOf(version) != 0;
})
.map(function (key) {
return caches.delete(key);
})
);
})
}
/*
trims the cache
If cache has more than maxItems then it removes the excess items starting from the beginning
*/
var trimCache = function (cacheName, maxItems) {
caches.open(cacheName)
.then(function (cache) {
cache.keys()
.then(function (keys) {
if (keys.length > maxItems) {
cache.delete(keys[0])
.then(trimCache(cacheName, maxItems));
}
});
});
};
//When the service worker is first added to a computer
self.addEventListener("install", function(event) {
event.waitUntil(updateStaticCache()
.then(function() {
return self.skipWaiting();
})
);
})
self.addEventListener("message", function(event) {
var data = event.data;
//Send this command whenever many files are downloaded (ex: a page load)
if (data.command == "trimCache") {
trimCache(version + "pages", 25);
trimCache(version + "images", 10);
trimCache(version + "assets", 30);
}
});
//Service worker handles networking
self.addEventListener("fetch", function(event) {
//Fetch from network and cache
var fetchFromNetwork = function(response) {
var cacheCopy = response.clone();
if (event.request.headers.get('Accept').indexOf('text/html') != -1) {
caches.open(version + 'pages').then(function(cache) {
cache.put(event.request, cacheCopy);
});
} else if (event.request.headers.get('Accept').indexOf('image') != -1) {
caches.open(version + 'images').then(function(cache) {
cache.put(event.request, cacheCopy);
});
} else {
caches.open(version + 'assets').then(function add(cache) {
cache.put(event.request, cacheCopy);
});
}
return response;
}
//Fetch from network failed
var fallback = function() {
if (event.request.headers.get('Accept').indexOf('text/html') != -1) {
return caches.match(event.request).then(function (response) {
return response || caches.match('/offline/');
})
} else if (event.request.headers.get('Accept').indexOf('image') != -1) {
return new Response('<svg width="400" height="300" 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' }});
}
}
//This service worker won't touch non-get requests
if (event.request.method != 'GET') {
return;
}
//For HTML requests, look for file in network, then cache if network fails.
if (event.request.headers.get('Accept').indexOf('text/html') != -1) {
event.respondWith(fetch(event.request).then(fetchFromNetwork, fallback));
return;
}
//For non-HTML requests, look for file in cache, then network if no cache exists.
event.respondWith(
caches.match(event.request).then(function(cached) {
return cached || fetch(event.request).then(fetchFromNetwork, fallback);
})
)
});
//After the install event
self.addEventListener("activate", function(event) {
event.waitUntil(clearOldCaches()
.then(function() {
return self.clients.claim();
})
);
});
if ('serviceWorker' in navigator) {
navigator.serviceWorker.register('https://brandonrozek.com/serviceworker.js', {scope: '/'});
window.addEventListener("load", function() {
if (navigator.serviceWorker.controller != null) {
navigator.serviceWorker.controller.postMessage({"command":"trimCache"});
}
});
}
@MKDan

This comment has been minimized.

Copy link

MKDan commented Oct 22, 2018

How this differs from https://gist.github.com/flavioso16/fa0bcb969bf432f55cba1b255d441e3a ---------> Is this just a minification? And the above is the full code?

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.