So I didn't want a certain script to be cached by the serviceworker I'm working on. That's how it wasn't in the array of assets and urls to cache.
When I tested the worker I got all assets and pages I had in the array, as expected. But I also found https://url/undefined | OK on the list in the cache storage (in Chrome and Firefox).
When I navigated to the URL (https://url/undefined) I got the contents of the script not being on the list in the first place.
Does it make sense?
Here the contents of the script when the error occured (note that there is a scriptfile not being listed which is part of the smashingconf install though, when I added that to the urlsToCache array the undefined cache item was gone):
/**
* smashingconf.serviceworker.js
*
* Author | Marco Hengstenberg
* Version | 1.5.0 (Dev)
*
* Purpose | The Service Worker makes smashingconf.com available offline. I've been following the tutorial at http://www.html5rocks.com/en/tutorials/service-worker/introduction/ by Matt Gaunt
* License | There is no license, no copyright, no warranty, no guarantee and no support for the code provided. Handle with care though!
*
* To Do | Make updates on contents automatically available with skipWaiting
**/
'use strict';
/*!
* This is a simple test to ensure that all of the ES2015 features used here are
* present in the browser before executing. If it fails, the worker will not be
* installed. As of March 2016, all browsers that support service worker APIs
* also support these features.
*/
try {
[
'var {$$test} = {$$test: null}',
'[$$test] = [null]',
'$$test = Object.assign({}, {})',
'$$test = (...args) => args',
'$$test = new Map()',
'$$test = new Set()',
'delete $$test'
].forEach(eval);
} catch (err) {
console.warn(err);
throw 'Service worker unmet feature dependencies';
}
/*!
* Prefix for all cache keys.
*
* It should be updated to a new unique value (e.g. timestamp) to force the
* service worker to update its registrations (causing reinstallation). Changing
* this value will result in all caches being deleted.
*/
const CACHE_NAME = 'devcache-1.5.0';
/*!
* This is the list of files to precache. These URLs will be fetched and added
* to the cache during the `install` event handling.
*
* If any of these files are missing, the caching for the entire set will fail,
* but the installation will continue (with the cache being empty initially).
*/
const urlsToCache = [
'/',
'/about',
'/app-icon-192x192.png',
'/app-icon-256x256.png',
'/app-icon-384x384.png',
'/app-icon-512x512.png',
'/assets/images/anniversary.png',
'/assets/images/background.png',
'/assets/images/buschi.png',
'/assets/images/confetti-vitaly.png',
'/assets/images/german-flag.png',
'/assets/images/hausi-mit-katzi-und-apfeli.png',
'/assets/images/katzi-kuchi-buschi.png',
'/assets/images/logo.svg',
'/assets/images/mystery-smashingconf.png',
'/assets/images/offline.png',
'/assets/images/scenery.png',
'/assets/images/social/email.png',
'/assets/images/social/lanyrd.png',
'/assets/images/social/twitter.png',
'/assets/images/soldout.png',
'/assets/images/spanish-flag.png',
'/assets/images/speakers/aagu.png',
'/assets/images/speakers/aagu-hov.png',
'/assets/images/speakers/adho.png',
'/assets/images/speakers/adho-hov.png',
'/assets/images/speakers/daru.png',
'/assets/images/speakers/daru-hov.png',
'/assets/images/speakers/demi.png',
'/assets/images/speakers/demi-hov.png',
'/assets/images/speakers/evlola.png',
'/assets/images/speakers/evlola-hov.png',
'/assets/images/speakers/lydaga.png',
'/assets/images/speakers/lydaga-hov.png',
'/assets/images/speakers/modi.png',
'/assets/images/speakers/modi-hov.png',
'/assets/images/speakers/ms.png',
'/assets/images/speakers/msh.png',
'/assets/images/speakers/nacu.png',
'/assets/images/speakers/nacu-hov.png',
'/assets/images/speakers/olre.png',
'/assets/images/speakers/olre-hov.png',
'/assets/images/speakers/pall.png',
'/assets/images/speakers/pall-hov.png',
'/assets/images/speakers/podema.png',
'/assets/images/speakers/podema-hov.png',
'/assets/images/speakers/sadr.png',
'/assets/images/speakers/sadr-hov.png',
'/assets/images/speakers/unkr.png',
'/assets/images/speakers/unkr-hov.png',
'/assets/images/union-jack-badge.png',
'/assets/images/usa-flag.png',
'/assets/styles/fr16.min.css',
'/attendees',
'/codeofconduct',
'/contact',
'/content/01-home/anniversary.png',
'/content/02-speakers/00-oliver-reichenstein/oliver-reichenstein.jpg',
'/content/02-speakers/00-una-kravets/una-kravetz.jpg',
'/content/02-speakers/01-polle-de-maagt/polle-de-magt.jpg',
'/content/02-speakers/02-sarah-drasner/sarah-drasner.jpg',
'/content/02-speakers/03-dave-rupert/dave-rupert.jpg',
'/content/02-speakers/04-eva-lotta-lamm/eva-lotta-lamm.jpg',
'/content/02-speakers/05-aaron-gustafson/aaron-gustafson.jpg',
'/content/02-speakers/05-lyza-danger-gardner/lyza-danger-gardner.jpg',
'/content/02-speakers/06-paul-lloyd/paul-lloyd.jpg',
'/content/02-speakers/07-monica-dinculescu/monica-dinculescu.jpg',
'/content/02-speakers/10-adrian-holovaty/adrian-holovaty.jpg',
'/content/02-speakers/11-denys-mishunov/denys-mishunov.jpg',
'/content/02-speakers/12-nathan-curtis/nathan-curtis.jpg',
'/content/02-speakers/15-the-mystery-speaker/mystery-alt.png',
'/content/04-workshops/03-eva-lotta-lamm/eva-lotta-lamm.jpg',
'/content/04-workshops/04-nathan-curtis/nathan-curtis.jpg',
'/content/04-workshops/04-vitaly-friedman/vitaly-friedman.jpg',
'/content/05-locations/parking-in-freiburg.png',
'/content/05-locations/02-hotels/01-intercity-hotel/hotel-intercity.jpg',
'/content/05-locations/02-hotels/02-hirschen-hotel/hotel-hirschen.png',
'/content/05-locations/02-hotels/03-rappen-hotel/rappen.jpg',
'/content/05-locations/02-hotels/04-best-western-victoria/hotel-best-western-victoria.jpg',
'/content/05-locations/02-hotels/06-city-hotel/cityhotel.jpg',
'/content/05-locations/02-hotels/07-hotel-am-stadtgarten/stadtgarten.jpg',
'/content/05-locations/02-hotels/08-park-hotel-post/park-hotel.jpg',
'/content/05-locations/02-hotels/09-hotel-rheingold/rheingold.jpg',
'/content/06-sponsors/01-wifi-lounge/00-microsoft/ms-edge.png',
'/content/06-sponsors/03-party-sponsor/00-virtual-identity/virtual-identity.png',
'/content/06-sponsors/03-silver/00-haufe-lexware/haufe-lexware.png',
'/content/06-sponsors/03-speaker-dinner-host/00-mediatemple/mediatemple.png',
'/content/06-sponsors/04-coffee/00-iconfinder/iconfinder.png',
'/content/06-sponsors/05-virtual/00-kirby/kirbyicon.png',
'/content/06-sponsors/05-virtual/00-startup-vitamins/startup-vitamins.jpg',
'/content/06-sponsors/05-virtual/00-stickermule/stickermule.jpg',
'/content/06-sponsors/05-virtual/00-tesla-amazing/ta-logo.png',
'/content/06-sponsors/05-virtual/00-typeform/typeform-logo.png',
'/content/06-sponsors/05-virtual/00-uxpassion/wot-opt.png',
'/content/07-about/freiburg-location.jpg',
'/content/07-about/workshops-preview.jpg',
'/favicon.ico',
'/favicon.png',
'/imprint',
'/locations',
'/offline',
'/registration',
'/schedule',
'/schedule/day:monday',
'/schedule/day:tuesday',
'/speakers',
'/speakers/oliver-reichenstein',
'/speakers/una-kravets',
'/speakers/polle-de-maagt',
'/speakers/sarah-drasner',
'/speakers/dave-rupert',
'/speakers/eva-lotta-lamm',
'/speakers/aaron-gustafson',
'/speakers/lyza-danger-gardner',
'/speakers/paul-lloyd',
'/speakers/monica-dinculescu',
'/speakers/adrian-holovaty',
'/speakers/denys-mishunov',
'/speakers/nathan-curtis',
'/speakers/the-mystery-speaker',
'/sponsors',
'/terms',
'/workshops',
'/workshops/eva-lotta-lamm',
'/workshops/nathan-curtis',
'/workshops/vitaly-friedman',
];
// Now, let's wait for the install-event
self.addEventListener('install', function(event) {
event.waitUntil(
caches.open(CACHE_NAME)
.then(function(cache) {
return cache.addAll(urlsToCache);
}).then(function() {
return self.skipWaiting();
}).catch(function() {
console.log('Oh noes. Seems the install event failed.');
})
);
});
// Then we can start fetching stuff
self.addEventListener('fetch', function(event) {
event.respondWith(
caches.match(event.request)
.then(function(response) {
// Cache hit - return response
if (response) {
return response;
}
// IMPORTANT: Clone the request. A request is a stream and
// can only be consumed once. Since we are consuming this
// once by cache and once by the browser for fetch, we need
// to clone the response
var fetchRequest = event.request.clone();
return fetch(fetchRequest).then(
function(response) {
// Check if we received a valid response
if(!response || response.status !== 200 || response.type !== 'basic') {
return response;
}
// IMPORTANT: Clone the response. A response is a stream
// and because we want the browser to consume the response
// as well as the cache consuming the response, we need
// to clone it so we have 2 stream.
var responseToCache = response.clone();
caches.open(CACHE_NAME)
.then(function(cache) {
cache.put(event.get, responseToCache);
});
return response;
}
);
})
);
});
// Activation
self.addEventListener('activate', function(event) {
var cacheWhitelist = CACHE_NAME;
event.waitUntil(
caches.keys().then(function(cacheNames) {
return Promise.all(
cacheNames.map(function(cacheName) {
if (cacheWhitelist.indexOf(cacheName) === -1) {
return caches.delete(cacheName);
}
})
);
})
);
return self.clients.claim();
});
This code in your fetch event handler should use
event.request
instead ofevent.get
: