NavigationPreloadManager
注意:此功能在Web Workers中可用。
NavigationPreloadManager
是Service Worker API的接口,提供用于管理与 Service Worker 启动并行预加载资源的方法。
如果受支持,此类型的对象将由ServiceWorkerRegistration.navigationPreload
返回。预加载获取请求的结果使用FetchEvent.preloadResponse
返回的 Promise 等待。
实例方法
-
设置在预加载请求中发送的
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
)。
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。
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
。
navigator.serviceWorker.ready
.then((registration) =>
registration.navigationPreload.setHeaderValue(newValue),
)
.then(() => {
console.log("Done!");
});
使用导航预加载加速 Service Worker > 预加载的自定义响应 提供了一个更完整的示例,其中文章网页的响应由缓存的页眉和页脚构建,以便仅为预取返回文章内容。
获取状态
您可以使用NavigationPreloadManager.getState()
检查导航预加载是否已启用,并确定使用Service-Worker-Navigation-Preload
HTTP 标头为预加载请求发送什么指令值。
以下代码显示了如何获取解析为 state
对象的 Promise 并记录结果。
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 表格仅在浏览器中加载
另请参阅
- 使用导航预加载加速 Service Worker (developer.chrome.com)