0
votes

I'm using a NetworkFirst strategy for a NavigationRoute in my workbox-based service worker, so that navigation requests will be served cached responses while the user is offline.

workbox.routing.registerRoute(
    new workbox.routing.NavigationRoute(
        new workbox.strategies.NetworkFirst({
            cacheName: 'static-pages',
        }),
    ),
);

When I navigate to a page, the navigation request gets cached, and then I can visit it again while offline. So far so good.

However, I need to pre-cache the PWA start URL, so if the user installs the PWA from any page, goes offline, and tries to open it, the PWA start URL is cached and available. In fact, this will be a requirement for the installability prompt as of Chrome 91.

self.addEventListener('activate', (event) => {
    event.waitUntil(
        caches.open('static-pages').then(cache => {
            const startUrl = 'https://my-pwa-start-url...';
            return cache.add(startUrl);
        })
    );
});

The issue here is that the request for startUrl is not a navigation request, so even though it gets cached in the static-pages cache, it is not used when navigating to the start URL.

I tried manually constructing a navigation request, e.g.

const startUrlRequest = new Request(startUrl, { mode: 'navigate' });
return cache.add(startUrlRequest);

But then I get this error:

TypeError: Failed to construct 'Request': Cannot construct a Request with a RequestInit whose mode member is set as 'navigate'.

Is there any way to pre-cache a NavigationRequest without actually navigating to the page?

1

1 Answers

1
votes

The basic approach that you're attempting—calling cache.add(startUrl)—should be fine, although I would recommend doing that in your install handler, not activate.

In general, there's no need to manually construct a navigation request and pass that to cache.add(), and as you've discovered, you can't actually construct one without throwing an exception.

The only thing "special" about navigation requests and cached responses is that a redirected response can't be used to satisfy a navigation request, so just make sure that the URL you're caching doesn't result in a 30x redirect.

So, my guess is that your cache is being properly pre-populated, but there's a cache miss in your NetworkFirst strategy. One possible explanation is the presence of query parameters in the URL that you explicitly cached, and a mismatch of those parameters in the URL that's being requested during navigation. You should be able to confirm that by using Chrome's DevTools to inspect the cache and the network traffic. If that's indeed the issue, you could tell Workbox to ignore the query parameters when it tries to find a matching cache entry by passing in the ignoreSearch match option:

new workbox.strategies.NetworkFirst({
  cacheName: 'static-pages',
  matchOptions: {
    ignoreSearch: true,
  },
})