NavigationPreloadManager
Baseline Widely available
This feature is well established and works across many devices and browser versions. It’s been available across browsers since April 2022.
Secure context: This feature is available only insecure contexts (HTTPS), in some or allsupporting browsers.
Note: This feature is available inWeb Workers.
TheNavigationPreloadManager interface of theService Worker API provides methods for managing the preloading of resources in parallel with service worker bootup.
If supported, an object of this type is returned byServiceWorkerRegistration.navigationPreload.The result of a preload fetch request is waited on using the promise returned byFetchEvent.preloadResponse.
In this article
Instance methods
NavigationPreloadManager.enable()Enables navigation preloading, returning a
Promisethat resolves withundefined.NavigationPreloadManager.disable()Disables navigation preloading, returning a
Promisethat resolves withundefined.NavigationPreloadManager.setHeaderValue()Sets the value of the
Service-Worker-Navigation-PreloadHTTP header sent in preloading requests and returns an emptyPromise.NavigationPreloadManager.getState()Returns a
Promisethat resolves to an object with properties that indicate whether preloading is enabled, and what value will be sent in theService-Worker-Navigation-PreloadHTTP header in preloading requests.
Description
Service workers handlefetch() events on behalf of a site, for pages within a given scope.When a user navigates to a page that uses a service worker, the browser boots up the worker (if it isn't already running), then sends it a fetch event and waits for the result.On receiving an event, the worker returns the resource from a cache if it is present, or otherwise fetches the resource from the remote server (storing a copy for returning in future requests).
A service worker cannot process events from the browser until it has booted.This is unavoidable, but usually doesn't have much impact.Service workers are often already started (they remain active for some time after processing other requests).Even if a service worker does have to boot, much of the time it may be returning values from a cache, which is very fast.However, in those cases where a worker has to boot before it can start fetching a remote resource, then the delay can be significant.
TheNavigationPreloadManager provides a mechanism to allow fetching of the resources to run in parallel with service worker boot, so that by the time the worker is able to handle the fetch request from the browser, the resource may already have been fully or partially downloaded.This makes the case where the worker has to start up "no worse" than when the worker is already started, and in some cases better.
The preload manager sends theService-Worker-Navigation-Preload HTTP header with preload requests, allowing responses to be customized for preload requests.This might be used, for example, to reduce the data sent to just part of the original page, or to customize the response based on the user's log-in state.
Examples
The examples here are fromSpeed up Service Worker with Navigation Preloads (developer.chrome.com).
Feature detection and enabling navigation preloading
Below we enable navigation preloading in the service worker'sactivate event handler, after first usingServiceWorkerRegistration.navigationPreload to determine if the feature is supported (this returns either theNavigationPreloadManager for the service worker orundefined if the feature is not supported).
addEventListener("activate", (event) => { event.waitUntil( (async () => { if (self.registration.navigationPreload) { // Enable navigation preloads! await self.registration.navigationPreload.enable(); } })(), );});Using a preloaded response
The following code shows a service worker fetch event handler that uses a preloaded response (FetchEvent.preloadResponse).
Thefetch event handler callsFetchEvent.respondWith() to pass a promise back to the controlled page.This promise will resolve with the requested resource, which may be from the cache, a preloaded fetch request, or a new network request.
If there is a matching URL request in theCache object, then the code returns a resolved promise for fetching the response from the cache.If no match is found in the cache, the code returns the resolved preloaded response (FetchEvent.preloadResponse).If there is no matching cache entry or preloaded response, the code starts a new fetch operation from the network and returns the (unresolved) promise for that fetch operation.
addEventListener("fetch", (event) => { event.respondWith( (async () => { // Respond from the cache if we can const cachedResponse = await caches.match(event.request); if (cachedResponse) return cachedResponse; // Else, use the preloaded response, if it's there const response = await event.preloadResponse; if (response) return response; // Else try the network. return fetch(event.request); })(), );});Custom responses
The browser sends the HTTP headerService-Worker-Navigation-Preload with preload requests, with a default directive value oftrue.This allows servers to differentiate between normal and preload fetch requests, and to send different responses in each case if required.
Note:If the response from preload and normal fetch operations can be different, then the server must setVary: Service-Worker-Navigation-Preload to ensure that the different responses are cached.
The header value can be changed to any other string value usingNavigationPreloadManager.setHeaderValue() in order to provide additional context for the prefetch operation.For example, you might set the value to the ID of your most recently cached resource, so that the server won't return any resources unless they are actually needed.Similarly, you could configure the returned information based on authentication status instead of using cookies.
The code below shows how to set the value of the header directive to some variablenewValue.
navigator.serviceWorker.ready .then((registration) => registration.navigationPreload.setHeaderValue(newValue), ) .then(() => { console.log("Done!"); });Speed up Service Worker with Navigation Preloads > Custom responses for preloads provides a more complete example of a site where the response for an article web page is constructed from a cached header and footer, so that only the article content is returned for a prefetch.
Getting the state
You can useNavigationPreloadManager.getState() to check whether navigation preloading is enabled and to determine what directive value is sent with theService-Worker-Navigation-Preload HTTP header for preload requests.
The code below shows how to get the promise that resolves to astate object and log the result.
navigator.serviceWorker.ready .then((registration) => registration.navigationPreload.getState()) .then((state) => { console.log(state.enabled); // boolean console.log(state.headerValue); // string });Specifications
| Specification |
|---|
| Service Workers Nightly> # navigation-preload-manager> |
Browser compatibility
See also
- Speed up Service Worker with Navigation Preloads (developer.chrome.com)