App Shell结构加载后动态内容无法更新怎么办?

东方玉哲 阅读 97

我在做PWA的App Shell结构时遇到问题,shell骨架加载成功了,但后续通过fetch获取的数据内容始终不更新。我用Cache.match缓存了shell页面,但数据接口返回的是旧数据,明明后端已经改过了。

尝试过在service worker里这样处理数据请求:


self.addEventListener('fetch', function(event) {
  if (event.request.url.includes('/api/data')) {
    event.respondWith(
      caches.match(event.request)
        .then(cacheRes => cacheRes || fetch(event.request))
    );
  }
});

清除浏览器缓存也没用,控制台没报错,就是显示旧数据。是不是缓存策略哪里写错了?怎么让动态数据能正常更新呢?

我来解答 赞 10 收藏
二维码
手机扫码查看
2 条解答
Mc.窅恒
Mc.窅恒 Lv1
你这代码写反了,典型的"缓存优先"策略用在动态接口上,那肯定一直是旧数据啊。

问题就在这行:cacheRes || fetch(event.request),意思是缓存有的话直接返回,根本不会去请求后端。App Shell的静态资源用缓存优先没问题,但API数据必须反过来。

动态数据要用"网络优先"策略,先请求网络,失败了再降级读缓存。改一下:

self.addEventListener('fetch', function(event) {
if (event.request.url.includes('/api/data')) {
event.respondWith(
fetch(event.request)
.then(networkRes => {
// 拿到新数据后更新缓存
const resClone = networkRes.clone();
caches.open('data-cache').then(cache => {
cache.put(event.request, resClone);
});
return networkRes;
})
.catch(() => {
// 网络挂了才读缓存
return caches.match(event.request);
})
);
}
});


这样每次都会先请求后端拿最新数据,只有网络不通时才用缓存兜底。

还有个坑,你之前存的旧缓存可能还在,先把Service Worker注销掉,然后在Application面板里手动清除掉Cache Storage里的缓存再测试。不然旧缓存一直存在那,caches.match还是能匹配到。

另外提一句,这种策略分离的写法,建议把静态资源和API请求的缓存分开存,caches.open的时候用不同的cache name,管理起来清晰很多。浏览器兼容方面现代浏览器都没问题,放心用。
点赞 3
2026-03-02 12:18
Code°书錦
问题出在缓存优先策略上,动态数据接口不能直接用 caches.match,得强制走网络请求。改一下代码逻辑:

self.addEventListener('fetch', function(event) {
if (event.request.url.includes('/api/data')) {
event.respondWith(
fetch(event.request).catch(() => caches.match(event.request))
);
}
});


先走网络,失败再回退到缓存,数据就能正常更新了。别忘了在后端给接口加个合适的 Cache-Control 响应头,比如 no-cache 或者短时间过期,避免被强缓存坑了。
点赞 8
2026-02-19 11:02