Navigation Preload是Service Worker并行发起主文档网络请求的机制,用于缓解其启动延迟导致的白屏卡顿;它不加速资源发现,仅优化HTML导航请求,需注册SW后在activate中启用、fetch中用waitUntil包裹preloadResponse处理。

Navigation Preload 是什么,它真能加速页面跳转?
Navigation Preload 不是让浏览器“提前加载目标页 HTML”,而是让 Service Worker 在启动过程中,并行发起对主文档的网络请求。它解决的是 Service Worker 启动延迟导致的白屏卡顿,不是资源发现慢的问题。如果你没注册 Service Worker,navigationPreload 配置完全无效。
怎么开启 Navigation Preload?必须写这三步
只在 Service Worker 注册时调用 navigationPreload.enable() 不够,必须同步完成以下三步:
- 在 Service Worker 的
activate事件里调用event.waitUntil(self.registration.navigationPreload.enable())(注意:不能只写enable(),否则可能失败) - 在
fetch事件中检查event.preloadResponse是否存在且为 Promise,再用await event.preloadResponse获取响应 - 必须用
event.waitUntil()包裹整个 fetch 处理逻辑,否则 preload 请求会在 Promise settle 前被取消 —— 这就是你看到 “The service worker navigation preload request was cancelled” 错误的直接原因
为什么 fetch 里拿到的 event.preloadResponse 总是 undefined?
常见原因有四个,按优先级排查:
- Service Worker 没激活成功:检查
chrome://serviceworker-internals/或 DevTools Application → Service Workers,确认状态是activated而非waiting - 导航请求没走 fetch 事件:确保 URL 是同源 HTML 文档,且没有被
skipWaiting()或clients.claim()干扰生命周期 - preload 被禁用:某些环境(如 Chrome 的“节电模式”、Firefox 隐私窗口)会强制关闭 Navigation Preload,可通过
navigator.serviceWorker.ready.then(r => r.navigationPreload.getState())检查返回值是否为"enabled" - fetch 事件监听器注册太晚:必须在 Service Worker 全局作用域顶层注册,不能包裹在
self.addEventListener('install', ...)内部
Navigation Preload 和 rel="preload" 能一起用吗?
能,但作用完全不同,别混用:
立即学习“前端免费学习笔记(深入)”;
-
rel="preload"是 HTML 解析阶段告诉浏览器“这个 CSS/JS/字体我马上要”,影响的是资源下载队列优先级,和 Service Worker 无关 - Navigation Preload 是 Service Worker 生命周期机制,只针对导航请求(即主 HTML 文档),不支持预加载子资源(图片、API、chunk JS)
- 两者叠加时,Service Worker 可以用
event.preloadResponse拿到 HTML,再从该响应中解析出<link rel="preload">标签并手动触发子资源预加载 —— 但这属于高级定制,需自行实现,浏览器不自动联动
最常被忽略的一点:Navigation Preload 的收益高度依赖网络 RTT 和 Service Worker 启动耗时。在本地开发或高速网络下几乎测不出差别,务必在 3G/4G 真机环境验证效果。



















