Library Affected:
sw-lib, sw-runtime-caching
It's fairly common, especially with images, to want to use a cache-first strategy, and if the URL isn't already in the cache and the network is unavailable, fallback to a previously cached "default" entry.
It's possible to get this behavior in sw-lib using something along the lines of:
// Assume that this URL is precached.
const FALLBACK_IMAGE_URL = '/images/fallback.png';
const imagesHandler = sw.strategies.cacheFirst();
swlib.router.registerRoute(new RegExp('/images/'), ({event}) => {
return imagesHandler.handle({event})
.catch(() => caches.match(FALLBACK_IMAGE_URL));
});
You can do something similar using the modules from sw-runtime-caching directly.
I wonder whether it makes sense to provide a helper to accomplish this? The most straightforward approach would be to add in an optional parameter to the cache-first handler constructor for the fallback URL.
An added wrinkle would be ensuring that the fallback URL is actually present in the cache, but rather than attempting to manage that cache entry, we could just use logging to let developers know if the fallback entry is missing.
Given sw-lib is a worrying size as it is, for now I'd suggest making this a recipe in docs and see if it gets used or not - if it does, then look to bake it in.
This has come up a few times (most recently by @codepunkt) and it's something that I wanted to bump up (though likely post-v3).
Ouch. If it is not possible to always serve a resource (in my case: all navigation routes) from network and only serve from cache when the user is offline right now, it's a deal breaker for me as it will completely negate all my server side rendering work.
Is this possible?
As mentioned in the other issue thread, here's another use case that we should try to accommodate, either directly via some sort of plugin, or at least better recipes:
const matcher = ({event}) => event.request.mode === 'navigate';
const handler = () => fetch('/app-shell.html').catch(() => caches.match('/offline.html'));
workboxSW.router.registerRoute(matcher, handler);
There are a number of ways that we can solve this and I'm pretty set that another config option isn't the right way to do it.
Other options:
.handle() call.Hi there, I found this is removed from V3 milestone, does that mean there will not be an official solution for this in V3?
Not at the moment no sorry.
@jeffposnick For some reason the code that you posted just didn't work for me but it did give me a clue as to where to start. The catch code just never got called when offline and it would show the default browser offline page.
I ended up getting getting it to work with the following code. Not sure if this is the best way to do it so any suggestions or improvements are appreciated.
In my use-case I want network first functionality, with fallback to cached pages when offline, and then
fallback to offline.html when there is a cache-miss.
Workbox 3 code:
var networkFirstHandler = workbox.strategies.networkFirst({
cacheName: 'default',
plugins: [
new workbox.expiration.Plugin({
maxEntries: 10
}),
new workbox.cacheableResponse.Plugin({
statuses: [200]
})
]
});
const matcher = ({event}) => event.request.mode === 'navigate';
const handler = (args) => networkFirstHandler.handle(args).then((response) => (!response) ? caches.match('/offline.html') : response);
workbox.routing.registerRoute(matcher, handler);
There's an updated recipe at https://developers.google.com/web/tools/workbox/guides/advanced-recipes#provide_a_fallback_response_to_a_route that outlines a generic fallback using workbox.routing.setCatchHandler() in Workbox v4.
I think we're going to stick to the recipe-based solution rather than explicitly adding to the core Workbox functionality.
Most helpful comment
@jeffposnick For some reason the code that you posted just didn't work for me but it did give me a clue as to where to start. The
catchcode just never got called when offline and it would show the default browser offline page.I ended up getting getting it to work with the following code. Not sure if this is the best way to do it so any suggestions or improvements are appreciated.
In my use-case I want network first functionality, with fallback to cached pages when offline, and then
fallback to offline.html when there is a cache-miss.
Workbox 3 code: