Service Worker 本身不预加载资源,需靠预缓存+导航预加载双轨协同:install阶段用addAll缓存静态骨架文件,注册时启用navigationPreload,fetch中优先响应preloadResponse。

Service Worker 本身不支持“预加载”——它不能在页面请求前主动触发浏览器的资源加载器,也不能像 那样让 HTML 解析器提前调度关键资源。真正能提升单页应用(SPA)首屏速度的,是预缓存(Precache)+ 导航预加载(Navigation Preload)双轨协同,配合合理的缓存策略和资源组织。
预缓存首屏静态骨架资源
这是用户首次访问时实现“秒开”的前提。必须在 Service Worker 的 install 阶段,把首页渲染所依赖的纯静态文件一次性存入 Cache API:
- 只缓存构建时确定的资源:如
/index.html(需是构建生成的、不含服务端动态内容的版本)、/app.css、/vendor.js、/logo.png等 - 使用
caches.open('v1-static').addAll([...])批量写入,并用event.waitUntil()保证安装完成前操作结束 - 避免缓存带时间戳、用户信息等动态字段的 HTML;这类内容更适合运行时缓存或由服务端直出
启用导航预加载,消除 SW 冷启动延迟
用户刷新或新打开页面时,Service Worker 启动需要时间,传统流程会卡住首屏。导航预加载让浏览器在 SW 初始化的同时,并行发起网络请求:
- 注册时立即启用:
navigator.serviceWorker.register('/sw.js').then(r => r.navigationPreload.enable()) - 在
fetch事件中优先使用event.preloadResponse,它是浏览器原生发起的响应,比 JS 层 fetch 更快、更可靠 - 对
destination === 'document'的请求单独处理,确保首页跳转不被阻塞
fetch 中实现缓存-预加载-网络三级响应策略
单次请求应有明确的 fallback 顺序,兼顾速度、新鲜度与容错性:
- 先检查
event.preloadResponse,存在则直接返回(最快路径) - 若无预加载响应,再查
caches.match(event.request)(命中即返回,支持离线) - 最后兜底
fetch(event.request),并用response.clone()同时返回给页面和更新缓存 - 注意:HTML 响应流只能消费一次,所有写入缓存或返回页面的操作都需基于 clone
主页面配合做资源发现与加载优化
Service Worker 是代理,不是调度器。真正决定“哪些资源该早加载”的,仍是主页面的 HTML 和 JS:
- 在
中用提前拉取关键 CSS - 内联首屏关键 CSS,避免阻塞渲染
- 对字体、大图等资源,用
rel="preload"或rel="preconnect"加速连接建立 - 避免在 SW 中尝试“模拟预加载”图片或第三方 CDN 资源——它们大多不支持 CORS,且无法触发浏览器预加载器










