Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add resources fetched prior to SW activation to the runtime cache when offline browsing is enabled #937

Open
westonruter opened this issue Mar 1, 2023 · 0 comments
Labels
enhancement New feature or request service-workers

Comments

@westonruter
Copy link
Collaborator

When offline browsing is enabled, pages and resources fetched are automatically added to the runtime cache. This is great because it prevents inadvertently precaching assets that won't be used (e.g. irrelevant image sizes) and it won't slow down installation of the service worker, which are both the case for the precaching. Nevertheless, a downside is that the resources fetched prior to the service worker being installed will not be added to the runtime cache. This means that if a user visits the site once and then leaves, nothing will be added to the runtime cache.

It turns out, however, there is a way to add such assets to the runtime cache manually upon activation of the service worker, and Workbox has it built-in as documented in Send the service worker a list of URLs to cache.

This is simple to implement for the PWA plugin today via an extension plugin.

Nevertheless, what can't currently be included in the runtime cache is the page initially loaded. This is explained in the Workbox docs:

The above technique works for any route defined via the registerRoute() method on the default router. If you're creating your own Router instance, you'll need to call its addCacheListener() method manually.

It's not clear if the Workbox docs are entirely accurate here, since we are using registerRoute() but we are nevertheless constructing a NavigationRouter instead of a Router:

wp.serviceWorker.routing.registerRoute(
new wp.serviceWorker.routing.NavigationRoute(
handleNavigationRequest,
{
denylist,
}
)
);

The reason that Workbox refuses to add the location.href here is that request.mode !== 'navigate' and so its matcher fails when the request is handled. I thought this could be worked around perhaps by forcing the mode to be 'navigate' when constructing the Request as follows:

const urlsToCache = [
	[ location.href, { mode: 'navigate' } ],
	...performance.getEntriesByType('resource').map(r => r.name),
];

But this results in an error:

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

Indeed, the docs for the mode property indicate:

A mode for supporting navigation. The navigate value is intended to be used only by HTML navigation. A navigate request is created only while navigating between documents.

But this restriction isn't explicitly stated in the constructor docs.

So, this can apparently still be achieved by calling the "addCacheListener() method manually". But this doesn't seem entirely feasible since workbox.routing doesn't expose the default router. What seems to be needed is to add a message event handler to service-worker-navigation-routing.js which will listen for a specific message like CACHE_NAVIGATION_URL. When received, we can request it and then pass the response into our handleNavigationRequest().

@westonruter westonruter added enhancement New feature or request service-workers labels Mar 1, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request service-workers
Projects
None yet
Development

No branches or pull requests

1 participant