When the JSAir service worker installs, it caches just the index page
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
// Here comes the install event! // This only happens once, when the browser sees this // version of the ServiceWorker for the first time. self.addEventListener('install', functiononServiceWorkerInstall(event) { console.log('install event', event) // We pass a promise to event.waitUntil to signal how // long install takes, and if it failed event.waitUntil( // We open a cache caches.open(currentCache).then(functionaddResourceToCache(cache) { return cache.addAll([ '/', ]) }) ) })
When the home page sends a request for a static resource it is intercepted
by the service worker.
1 2 3 4 5 6 7 8 9 10 11 12
// The fetch event happens for the page request with the // ServiceWorker's scope, and any request made within that // page self.addEventListener('fetch', functiononServiceWorkerFetch(event) { console.log('fetch event', event) // Calling event.respondWith means we're in charge // of providing the response. We pass in a promise // that resolves with a response object event.respondWith( ... ) })
The fetch event handling first tries to call the network and actually
fetch the requested resource.
1 2 3 4 5 6 7 8 9
event.respondWith( fetch(event.request).then(functionupdateCacheAndReturnNetworkResponse(networkResponse) { console.log(`fetch from network for ${event.request.url} successfull, updating cache`) caches.open(currentCache).then(functionaddToCache(cache) { return cache.add(event.request) }) return networkResponse }) )
Note how the fetched result is added to the cache on success.
If the network is unavailable (offline mode) or the server is not responding
for any reason, the fetch promise will be rejected and the service worker
tries to lookup the requested resource in the cache.
1 2 3 4 5 6 7 8 9
fetch(event.request).then(functionupdateCacheAndReturnNetworkResponse(networkResponse) { ... }).catch(functionlookupCachedResponse(reason) { // On failure, look up in the Cache for the requested resource console.log(`fetch from network for ${event.request.url} failed:`, reason) return caches.match(event.request).then(functionreturnCachedResponse(cachedResponse) { return cachedResponse }) })
Hopefully in offline mode the requested resource has been cached already.
Otherwise the caches.match(event.request) promise is rejected too and the
index page receives 404 response automatically.
Waiting for the network request to fail leads to 300ms delay before the
cached resource is returned. You can see this by turning the WiFi off
and reloading the JSAir page with the Network DevTools tab open.
This service worker tries cache-first policy for the intercepted resources
1 2 3 4 5 6 7 8
self.addEventListener('fetch', function (event) { event.respondWith(self.caches.open(CACHE_NAME).then(function (cache) { return cache.match(event.request).then(function (response) { if (response) return response; return self.fetch(event.request); }); })); });
First, it will look up the resource in the cache, and if it unavailable will
make the network request.
Note the network response is NOT put into the cache. Instead of caching
every received response, the Zeit.co index page explicitly sends a message
to the service worker, asking to prefetch a specific resource.