Reputation: 12688
I'm working on an authoring / CMS type application. The application allows concurrent editing of various 'blocks' of data. It has supported offline using appache and indexDB. With this approach I know if my data is coming from the network or from the cache. Now I'd like to migrate things to use service workers and the new cache api.
I need a way to know if my data (request) was served from the cache or the network so I can inform the users they are possibly looking at stale data so any any edits may override data they don't know about. IMO, this would a pretty common thing to do but it's turning out not to be so easy...
I'm currently trying to get things working using WorkBox but I'd be more than happy with a native solution. Using Workbox I've tried to set a new header on the response but Chrome complains about
const apiStrategy = workbox.strategies.cacheFirst({
cacheName: 'data-cache',
cacheExpiration: {
maxEntries: 100,
maxAgeSeconds: 3600 * 24
},
cacheableResponse: { statuses: [200] }
});
workbox.routing.registerRoute(
new RegExp('/api/'),
async ({event, url}) => {
const cachedResponse = await apiStrategy.handle({event, url});
if (cachedResponse) {
const responseClone = cachedResponse.clone();
responseClone.headers.set('x-sw-cache', 'yes');
return responseClone;
}
return cachedResponse;
}
);
So is there any way to know if the response came from the network or the cache?
Upvotes: 3
Views: 2468
Reputation: 12688
Turns out there's a bunch of plugins. I was able to get what I needed using the custom cacheWillUpdate
plugin. My code now looks like
workbox.routing.registerRoute(
new RegExp('/api/'),
new workbox.strategies.NetworkFirst({
cacheName: 'data-cache',
cacheExpiration: {
maxEntries: 100,
maxAgeSeconds: 3600 * 24
},
cacheableResponse: { statuses: [ 200 ] },
plugins: [
{
cacheWillUpdate: ({ response }) => {
return newResponse(response.clone(), (headers) => {
headers.set("x-sw-cache", 'yes');
return headers;
});
}
}
]
})
);
const newResponse = (res, headerFn) => {
const cloneHeaders = () => {
const headers = new Headers();
for (const kv of res.headers.entries()) {
headers.append(kv[0], kv[1]);
}
return headers;
};
const headers = headerFn ? headerFn(cloneHeaders()) : res.headers;
return new Promise((resolve) => {
return res.blob().then((blob) => {
resolve(new Response(blob, {
status: res.status,
statusText: res.statusText,
headers: headers
}));
});
});
};
The newReponse
function was taken from How to alter the headers of a Response? thanks @mjs!
I can now check for the x-sw-cache
header to inform my users they may be looking at state data. :)
Upvotes: 4
Reputation: 29
if you look in browser's dev tools (i.e. chrome) switch to the network tab it will show as (from ServiceWorker). Also if you enable debugging workbox outputs all you need to know in the console.
Upvotes: 0