第一次加载Service Worker后,脱机再刷新,无法获取CacheStorage某些缓存的资源
对于很多网上的例子,监听fetch,并使用:caches.match获取缓存数据时
self.addEventListener('fetch', function (e) {
e.respondWith(
caches.match(e.request).then(res => {
...
在第一次挂载service worker时,我们使用cache.addAll()来将cacheList中指定路径的资源转移到缓存中。
const cacheList = ['./index.html',...]
self.addEventListener('install', e => {
e.waitUntil(
caches.open(cacheName)
.then(cache => {
return cache.addAll(cacheList);
})
.then(() => self.skipWaiting()),
);
});
问题与步骤
- 手动清除Service Worker,及caches缓存。
- 第一次加载页面后,马上脱机,然后再刷新。
- caches.match(e.request) ,一些特殊的资源会返回undefined,也就是找不到。
- 控制台查看缓存是有数据的。
- 联网状态下,刷新一次后,再脱机,则缓存资源能正常获取。
这个可以理解,因为这次刷新是在Service Worker生效的条件下。 那么网页中的资源请求都会被Service Worker 的fetch事件拦截,并以e.request 为key添加到cache缓存中。
调查
获取缓存失败的资源的特征:
- html 页面中<script type="module" >的资源
- css 中通过@font-face 引入的字体文件(.ttf) (验证了background:url引入的图片没有问题)
因此初步得出结论:
以上形式的资源,不能通过caches.match(Response) 的形式获取——由cache.addAll(cacheList) 缓存的数据
解决方案
caches.match(e.request.url),传入静态资源的url,可正常获取缓存数据。
猜测原因
可能是与这些资源第一次缓存时,存入的CacheStorage的 key不匹配导致的。
因为第一次进入的缓存是通过 cache.addAll 缓存,其缓存到cache的key为何值不清楚,导致二次脱机刷新时获取不到资源。而实际上已经有缓存。
截至写这篇文章时(2022-07-27)时,MDN(CacheStorage)上依旧为实验性。
根据CacheStorage.match(request, options) MDN 文档,其方法有第二个参数,options,它可以一定程度控制match的匹配规则。
从options.ignoreSearch 看出,匹配规则中会判断同一个url的参数是否相同。(这并不是原因)
未实际查明原因。
样本较少,若有错误或补充,敬请指出更正。