预缓存关键基底文件(HTML、CSS、JS、图标)并结合Cache-First策略与导航预加载,可显著降低首屏时延。Service Worker在install事件中预缓存必需资源,fetch事件中优先响应缓存,未命中则回源并缓存,导航预加载则保障版本更新时的平滑过渡。

直接缓存关键基底文件(HTML、CSS、JS、图标)是降低首屏网络往返时延最有效的方式之一。Service Worker 能在安装阶段就将这些资源存入 Cache Storage,后续访问时完全绕过网络请求,首屏渲染从“等资源下载”变成“读本地缓存”,延迟趋近于 0ms。
只缓存真正影响首屏的基底文件
预缓存不是越多越好。应聚焦首次渲染必需、体积可控、版本稳定的资源:
- 首页 HTML 文件(建议构建时生成带哈希的固定路径,或内联关键 CSS 避免阻塞)
- 首屏布局与样式必需的 CSS(如 reset.css、layout.css、theme.css)
- 驱动首屏交互的核心 JS(main.js、vendor.js,避免打包过大,可配合 webpack splitChunks 拆分)
- 关键图标(favicon、logo、loading 图标等小尺寸静态图)
图片、字体、视频、非首屏路由组件等不参与首屏渲染的资源,不应放入预缓存清单,否则会拖慢 Service Worker 安装,反而延长首次加载时间。
安装阶段完成预缓存,且仅触发一次
预缓存逻辑必须写在 install 事件中,并用 event.waitUntil() 包裹,确保所有资源写入缓存后才进入激活状态:
self.addEventListener('install', event => {
const urlsToCache = [
'/',
'/styles/layout.css',
'/js/main.js',
'/images/logo.svg'
];
event.waitUntil(
caches.open('base-v1').then(cache => cache.addAll(urlsToCache))
);
});
这个过程只在首次注册或 Service Worker 版本变更(脚本内容变化)时执行,因此 urlsToCache 必须准确、可访问,且路径与实际部署一致。
fetch 阶段对导航请求启用 Cache-First
用户打开页面时,浏览器发起的是 destination === 'document' 的导航请求。此时需立即匹配缓存,命中即返回,不发网络请求:
- 调用
caches.match(event.request)查找已缓存的 HTML - 若命中,直接
event.respondWith(response) - 若未命中,再调用
fetch(event.request)回源,并把响应存入缓存供下次使用
注意:必须在 fetch 事件中第一时间调用 event.respondWith(),否则浏览器会忽略 Service Worker 处理,走默认网络流程。
搭配导航预加载兜底新版本冷启动
当 Service Worker 更新后,首次访问可能因新脚本初始化耗时导致白屏。启用导航预加载可并行处理:
- 注册时调用
registration.navigationPreload.enable() - 在 fetch 事件中检查
event.preloadResponse - 若有预加载响应,直接返回;否则走缓存 → 网络 fallback 流程
这样既保证了旧版缓存可用时的极速响应,又避免了更新期间的加载空白,实现平滑过渡。

















