I have a single-page application with a dynamic URL generated using a token, for example: example.com/XV252GTH
, which includes various assets such as CSS and favicon.
This is how I implement the Service Worker registration:
navigator.serviceWorker.register('sw.js');
In the sw.js
file, I pre-cache the assets during installation:
var cacheName = 'v1';
var cacheAssets = [
'index.html',
'app.js',
'style.css',
'favicon.ico'
];
function precache() {
return caches.open(cacheName).then(function (cache) {
return cache.addAll(cacheAssets);
});
}
self.addEventListener('install', function(event) {
event.waitUntil(precache());
});
It's important to note that the index.html
page (which registers the Service Worker) is essentially a template that gets populated on the server before being sent to the client. Therefore, during the pre-caching phase, only the template is cached, not the actual page content.
During the fetch event, any requested resource that isn't in the cache is copied into it:
addEventListener('fetch', event => {
event.respondWith(async function() {
const cachedResponse = await caches.match(event.request);
if (cachedResponse) return cachedResponse;
return fetch(event.request).then(updateCache(event.request));
}());
});
This is achieved through the use of the updateCache function:
function updateCache(request) {
return caches.open(cacheName).then(cache => {
return fetch(request).then(response => {
const resClone = response.clone();
if (response.status < 400)
return cache.put(request, resClone);
return response;
});
});
}
At this point, all assets are cached but not the dynamically generated page. Only after a reload can another entry like /XV252GTH
be seen in the cache. The app is now offline-ready, however, this reloading process somewhat undermines the purpose of the Service Worker.
Question: How can I send a request (/XV252GTH
) from the client (the page registering the worker) to the Service Worker? Perhaps setting up a listener in sw.js
would work:
self.addEventListener('message', function(event){
updateCache(event.request)
});
But ensuring that it will be executed in a timely manner, i.e., sent by the client after the SW has finished installing, remains a challenge. What would be a best practice to handle this scenario?