NavigationPreloadManager

安全上下文:此功能仅在安全上下文(HTTPS)中可用,在部分或所有支持的浏览器中。

注意:此功能在Web Workers中可用。

NavigationPreloadManagerService Worker API的接口,提供用于管理与 Service Worker 启动并行预加载资源的方法。

如果受支持,此类型的对象将由ServiceWorkerRegistration.navigationPreload返回。预加载获取请求的结果使用FetchEvent.preloadResponse返回的 Promise 等待。

实例方法

启用导航预加载,返回一个Promise,该 Promise 解析为undefined

禁用导航预加载,返回一个Promise,该 Promise 解析为undefined

设置在预加载请求中发送的Service-Worker-Navigation-Preload HTTP 标头的值,并返回一个空的Promise

返回一个Promise,该 Promise 解析为一个对象,该对象包含指示是否启用了预加载以及在预加载请求中Service-Worker-Navigation-Preload HTTP 标头中将发送什么值的属性。

描述

Service Workers 代表某个站点处理给定范围内页面的fetch()事件。当用户导航到使用 Service Worker 的页面时,浏览器会启动工作线程(如果尚未运行),然后向其发送 fetch 事件并等待结果。收到事件后,工作线程会从缓存中返回资源(如果存在),否则从远程服务器获取资源(存储一份副本以供将来请求使用)。

Service Worker 在启动之前无法处理来自浏览器的事件。这是不可避免的,但通常不会产生太大影响。Service Workers 通常已经启动(在处理其他请求后会保持一段时间活动)。即使 Service Worker 需要启动,很多时候它也可能从缓存中返回值,这非常快。但是,在工作线程必须在开始获取远程资源之前启动的情况下,延迟可能会很大。

NavigationPreloadManager提供了一种机制,允许获取资源与 Service Worker 启动并行运行,以便在工作线程能够处理来自浏览器的 fetch 请求时,资源可能已经完全或部分下载。这使得工作线程必须启动的情况“不比”工作线程已启动的情况更差,在某些情况下甚至更好。

预加载管理器发送Service-Worker-Navigation-Preload HTTP 标头以及预加载请求,允许自定义预加载请求的响应。例如,这可以用于将发送的数据减少到原始页面的部分内容,或根据用户的登录状态自定义响应。

示例

此处的示例来自使用导航预加载加速 Service Worker(developer.chrome.com)。

功能检测和启用导航预加载

在下面,我们在 Service Worker 的 activate 事件处理程序中启用导航预加载,首先使用ServiceWorkerRegistration.navigationPreload确定该功能是否受支持(这将返回 Service Worker 的 NavigationPreloadManager 或如果该功能不受支持则返回 undefined)。

js
addEventListener("activate", (event) => {
  event.waitUntil(
    (async () => {
      if (self.registration.navigationPreload) {
        // Enable navigation preloads!
        await self.registration.navigationPreload.enable();
      }
    })(),
  );
});

使用预加载响应

以下代码显示了一个 Service Worker fetch 事件处理程序,该处理程序使用预加载响应(FetchEvent.preloadResponse)。

fetch 事件处理程序调用FetchEvent.respondWith()将 Promise 传回受控页面。此 Promise 将解析为请求的资源,该资源可能来自缓存、预加载获取请求或新的网络请求。

如果Cache对象中存在匹配的 URL 请求,则代码将返回一个已解析的 Promise 以从缓存中获取响应。如果在缓存中找不到匹配项,则代码将返回已解析的预加载响应(FetchEvent.preloadResponse)。如果没有匹配的缓存条目或预加载响应,则代码将从网络开始新的获取操作并返回该获取操作的(未解析的)Promise。

js
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);
    })(),
  );
});

自定义响应

浏览器使用 HTTP 标头Service-Worker-Navigation-Preload发送预加载请求,默认指令值为 true。这允许服务器区分普通获取请求和预加载获取请求,并在必要时在每种情况下发送不同的响应。

注意:如果预加载和普通获取操作的响应可能不同,则服务器必须设置 Vary: Service-Worker-Navigation-Preload 以确保缓存不同的响应。

可以使用NavigationPreloadManager.setHeaderValue()将标头值更改为任何其他字符串值,以便为预取操作提供其他上下文。例如,您可以将值设置为最近缓存的资源的 ID,以便服务器仅在实际需要时返回任何资源。类似地,您可以根据身份验证状态配置返回的信息,而不是使用 Cookie。

以下代码显示了如何将标头指令的值设置为某个变量 newValue

js
navigator.serviceWorker.ready
  .then((registration) =>
    registration.navigationPreload.setHeaderValue(newValue),
  )
  .then(() => {
    console.log("Done!");
  });

使用导航预加载加速 Service Worker > 预加载的自定义响应 提供了一个更完整的示例,其中文章网页的响应由缓存的页眉和页脚构建,以便仅为预取返回文章内容。

获取状态

您可以使用NavigationPreloadManager.getState()检查导航预加载是否已启用,并确定使用Service-Worker-Navigation-Preload HTTP 标头为预加载请求发送什么指令值。

以下代码显示了如何获取解析为 state 对象的 Promise 并记录结果。

js
navigator.serviceWorker.ready
  .then((registration) => registration.navigationPreload.getState())
  .then((state) => {
    console.log(state.enabled); // boolean
    console.log(state.headerValue); // string
  });

规范

规范
Service Workers
# navigation-preload-manager

浏览器兼容性

BCD 表格仅在浏览器中加载

另请参阅