Skip to content

Instantly share code, notes, and snippets.

@sethbergman
Last active February 16, 2018 01:29
Show Gist options
  • Save sethbergman/c108e93dce1e272894726d50d7e1f77d to your computer and use it in GitHub Desktop.
Save sethbergman/c108e93dce1e272894726d50d7e1f77d to your computer and use it in GitHub Desktop.
Service Worker Demo
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>GistRun</title>
</head>
<body>
<h1>Hello world!</h1>
<script src="main.js"></script>
<!--<script src="worker.js"></script>-->
<link rel="self" href="worker.js" scope="/">
</body>
</html>
'use strict';
(() => {
function createResponse(file) {
let responseInit = {
status: 200,
statusText: 'OK',
headers: {
'Content-Type': file.type
}
};
return new Response(file.content, responseInit);
}
function createUrl(clientID, name) {
return new URL(`/run/${clientID}/${name}`, location.href);
}
function createRequest(clientID, file) {
let url = createUrl(clientID, file.name);
return new Request(url, { mode: 'no-cors' });
}
function putFile(cache, clientID, file) {
let response = createResponse(file);
let request = createRequest(clientID, file);
return cache.put(request, response);
}
function updateFile(clientID, file) {
return caches.open(clientID)
.then(cache => putFile(cache, clientID, file));
}
function deleteFile(clientID, file) {
let request = createRequest(clientID, file);
return caches.open(clientID)
.then(cache => cache.delete(request));
}
function resetFiles(clientID, files) {
return caches.delete(clientID)
.then(() => caches.open(clientID))
.then(cache => Promise.all(files.map(file => putFile(cache, clientID, file))));
}
function handleMessage(event) {
if (!event.data.action || !event.ports.length === 1) {
return;
}
let data = event.data;
let responsePort = event.ports[0];
let clientID = data.clientID;
let action = data.action;
let handler;
switch (action) {
case 'updateFile':
handler = updateFile(clientID, data.file);
break;
case 'deleteFile':
handler = deleteFile(clientID, data.file);
break;
case 'resetFiles':
handler = resetFiles(clientID, data.files);
break;
default:
throw new Error(`Unknown action: ${action}`);
return;
}
handler.then(() => responsePort.postMessage('ok'));
}
self.addEventListener('message', handleMessage);
function handleFetch(event) {
let request = event.request;
if (!/\/run\//.test(request.url)) {
return;
}
let options = {}; // chrome does not support these yet: { ignoreSearch: true, ignoreMethod: true, ignoreVary: true };
event.respondWith(caches.match(request, options)
.then(response => response ? response : fetch(request)));
}
self.addEventListener('fetch', handleFetch);
})();
'use strict';
self.addEventListener('install', event => {
// The skipWaiting() method allows this service worker to progress from the registration's
// waiting position to active even while service worker clients are using the registration.
// https://slightlyoff.github.io/ServiceWorker/spec/service_worker/index.html#service-worker-global-scope-skipwaiting
event.waitUntil(self.skipWaiting());
});
self.addEventListener('activate', event => {
// The claim() method of the of the Clients interface allows an active Service Worker to set
// itself as the active worker for a client page when the worker and the page are in the same
// scope. This triggers an oncontrollerchange event on any client pages within the Service
// Worker's scope.
// https://slightlyoff.github.io/ServiceWorker/spec/service_worker/index.html#clients-claim-method
event.waitUntil(self.clients.claim());
});
self.importScripts('main.js');
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment