如何让Service Worker区分需缓存与禁止缓存的资源?
可落地的分层透传策略(核心逻辑:不让Service Worker靠猜做决策)
因为Service Worker本身不持有页面业务上下文,所有缓存判断的依据必须由持有上下文的页面侧主动透传,从请求链路里带明确的决策信号,从根本上解决两类图片资源无法区分的问题。
具体实现方案
方案1:通过URL参数透传决策标记(最易落地)
- 页面侧在发起资源请求时,主动给不同场景的图片URL追加约定的决策参数:
- 极少变更的用户头像:追加
?cache-rule=persist-forever - 实时更新的无限滚动图片:追加
?cache-rule=no-persist
- 极少变更的用户头像:追加
- 服务端/CDN只需要把查询参数作为缓存键的一部分,不需要因为参数改动响应的图片内容,完全兼容现有资源链路
- Service Worker侧拦截请求时,只需要解析URL中的
cache-rule参数执行对应逻辑:- 匹配到
persist-forever:走缓存优先策略,未命中时拉取资源并写入持久化缓存,设置长缓存周期 - 匹配到
no-persist:完全跳过缓存读写逻辑,直接走纯网络请求,哪怕本地存在同路径的旧缓存也绝不读取,同时不把这类资源写入持久化缓存 - 没有携带参数的通用请求:走预设的兜底默认策略,避免规则漏覆盖
这个方案的优势是不需要额外的跨域配置,兼容性最好,哪怕是直接通过<img>标签加载的资源也可以通过在URL里提前拼好参数的方式透传信号
- 匹配到
方案2:通过自定义请求头透传决策标记(适合不想修改URL的场景)
- 页面侧通过
fetch()发起请求时,在请求头中加入自定义字段传递决策,比如给持久化缓存的头像加X-SW-Cache: save,给禁止缓存的实时图加X-SW-Cache: skip - 跨域请求场景下,需要服务端在CORS配置中把对应自定义头加入
Access-Control-Allow-Headers列表,避免浏览器拦截请求 - Service Worker侧拦截请求时,直接读取请求头中的决策字段执行匹配逻辑,和URL参数方案的处理逻辑完全一致
方案3:预注册规则通道(适合批量加载的无限滚动场景)
- 对于Pinterest这类无限滚动的批量图片加载场景,页面侧在发起整批资源请求前,通过
postMessage把即将加载的资源URL集合和对应的缓存决策批量同步给Service Worker - Service Worker收到消息后,把这批URL对应的决策规则存在临时内存Map中,匹配到对应请求时按预注册规则处理;等这批请求全部完成后,自动清除对应的临时规则,避免长期占用内存
避坑要点
- 绝对不要让Service Worker靠域名、文件扩展名这类通用特征判断缓存规则:同一路径下可能同时存在需要长期缓存的头像和需要实时更新的动态图,靠通用规则100%会出现误判
- 对于无限滚动的动态图片,不要绝对禁止临时短时缓存:可以给这类资源设置10秒以内的极短内存缓存,避免短时间滚动时的重复网络请求,同时绝不将这类资源写入持久化存储,防止无限制占满Service Worker的缓存配额
- 规则优先级要明确:请求携带的显式决策信号 > 预注册的临时规则 > 全局兜底策略,避免多规则冲突
内容的提问来源于stack exchange,提问作者martinzen
相关产品推荐
相关产品推荐

