Search code examples
javascriptservice-workerworkbox

registerRoutes after login - google workbox sw


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.


Solution

  • 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.