service worker可通过预缓存占位图实现图片加载失败兜底:安装阶段缓存/placeholder.svg等资源,fetch事件中按资源类型拦截、缓存匹配、网络请求+超时控制,失败时返回预缓存图,并辅以调试与监控措施。

当网络异常或资源加载失败时,Service Worker 可以拦截请求并返回一张预缓存的占位图(如灰色方块、加载中图标),避免页面出现空白或报错。关键在于拦截请求、判断资源类型、匹配缓存策略,并在失败时 fallback 到兜底图。
预缓存占位图资源
在 Service Worker 安装阶段,把占位图(如 /placeholder.svg 或 /fallback.jpg)加入缓存,确保它始终可用:
- 使用 workbox-precaching 自动处理哈希校验和版本更新
- 或手动调用 caches.open().put() 缓存一个响应对象(需注意响应体只能读取一次,建议用 Response.clone() 备份)
- 推荐将占位图放在项目静态目录下,路径固定且无需动态生成
拦截图片请求并实现兜底逻辑
在 fetch 事件中,识别图片资源(通过 URL 后缀或 request.destination === 'image'),尝试从缓存或网络获取;任一环节失败,就返回预缓存的占位图:
- 先检查缓存中是否存在该图片(caches.match()),命中则直接返回
- 未命中则发起网络请求(fetch()),用 Promise.race([fetch(), timeout]) 防止卡死
- 若 fetch 拒绝、超时或响应状态非 2xx,跳过错误处理,直接 return caches.match('/placeholder.svg')
- 注意:对 CORS 图片,需在 fetch 时加 mode: 'no-cors',但会导致无法判断状态码;此时更依赖缓存命中或超时兜底
区分不同兜底场景(可选增强)
可根据请求上下文提供更合理的 fallback,提升体验:
- 对
标签请求(destination === 'image'),返回小尺寸 SVG 占位图,体积小、可缩放
- 对 CSS 中的 background-image 请求(通常 destination 是 'subresource'),可返回带透明背景的 base64 图片,避免布局突变
- 对关键首屏图片,可在 HTML 中预先写入 src="/placeholder.svg",再由 SW 后续替换为真实地址(需配合自定义 header 或 query 参数标识)
避免缓存污染与调试技巧
兜底逻辑上线后容易掩盖真实问题,需做好隔离和可观测性:
- 仅对明确的图片资源启用兜底,不作用于脚本、样式、API 等其他类型
- 在 DevTools 的 Application → Service Workers 中勾选 “Update on reload”,并禁用缓存(Network → Disable cache)方便调试
- 在 fetch 处理中添加 console.debug() 日志(注意生产环境移除),记录被兜底的 URL 和原因
- 可通过自定义响应 header(如 X-Fallback: true)让前端 JS 感知是否命中兜底,用于埋点或用户提示
不复杂但容易忽略:占位图本身必须是预缓存的,不能在 fetch 里动态 fetch 占位图再返回——否则兜底链路会再次失败。










