I have a SPA written in vanilla js, which handles routes with prefix - /mail, I want to cache the app shell here and use it for all the child routes like /mail/settings, /mail/inbox... etc, This SPA is served by app.html, after login. So I was using this -
//this has to be precached for the below createHandlerBoundToURL
workbox.precaching.precacheAndRoute([{
url:"/mail"
}
])
var pagesRouteHandler = workbox.precaching.createHandlerBoundToURL('/mail');
//I need this for dynamic url caching,
var navigationRoutes = new workbox.routing.NavigationRoute(pagesRouteHandler, {
allowlist: [
new RegExp('/mail/*'),
],
});
workbox.routing.registerRoute(navigationRoutes);
This worked fine when I was registering the service worker after login.(navigator.serviceWorker.register('/sw.js');
)
But now, I want to cache the login/signup screens also,which are separate html files, i.e outside SPA. And when I register the service worker in these html files, The above code tries to precache /mail
route, by making a get request. But the response will be a redirect to the login page by the server in the absence of a server session, so the same login.html
will be precached as /mail
route instead of actual SPA shell(html).
So, I want to register the above /mail and the dynamic routes after login or after /mail route is properly registered(like in a callback of registering /mail
route). How do I do this?
Note: I cannot send app.html to /mail
(as app shell) from server, without user session, since it is a template rendered with user values.
I solved this by the following method, Instead of precaching the root path, I am caching it as a normal route,
workbox.routing.registerRoute("/mail",new workbox.strategies.StaleWhileRevalidate({
cacheName: "appShell",
}));
And for all the child routes(since they are handled by frontend itself and need the same "/mail" app shell), I am registering a RegExp route that is to be handled from cache.
workbox.routing.registerRoute(({ url, event }) => {
return new RegExp(/(\/mail\/.*)/).test(url.pathname);
}, ({ url, event, params }) => {
if (event.request.mode === "navigate") {
// Always respond to navigations with the cached /mail, regardless of the underlying event.request.url value.
event.respondWith(caches.match("/mail"));//cache.match(...) is a promise
}
};);
While this is working for me, I would like a more informed and better solution, probably some library inbuilt functionality.
Also, there is an issue here that, if for some reason, the cache "/mail" is deleted, then the page would show offline, even when the network connection is on.