Service Worker 缓存 HTML 后页面不更新怎么办?

长孙金静 阅读 5

我用 Service Worker 做了离线缓存,把首页 index.html 也缓存了,但改了 HTML 内容后刷新页面还是旧的,哪怕关掉再开浏览器也没用。是不是缓存策略写错了?

我注册 SW 的方式是这样的:

<script>
if ('serviceWorker' in navigator) {
  window.addEventListener('load', () => {
    navigator.serviceWorker.register('/sw.js');
  });
}
</script>
我来解答 赞 4 收藏
二维码
手机扫码查看
1 条解答
欣炅 Dev
这问题太经典了,Service Worker 缓存 HTML 最大的坑就在这儿。

根本原因:SW 缓存了 index.html 后,除非你手动更新缓存,否则它会一直用旧的。你现在用的是 CacheFirst 或者没指定策略,默认就是缓存优先。

解决方案有两个思路:

方案一:改用网络优先策略(推荐)

在 sw.js 的 fetch 事件里,对 HTML 请求用 networkFirst:

self.addEventListener('fetch', event => {
if (event.request.url.endsWith('/') || event.request.url.endsWith('index.html')) {
event.respondWith(
fetch(event.request).catch(() => caches.match('/index.html'))
);
return;
}
// 其他资源用缓存优先...
});


这样每次请求 HTML 都会先尝试网络,网络不通才用缓存。

方案二:缓存 versioning

如果你想用缓存优先(更快),那就得在更新 HTML 时同时更新缓存。最简单的做法是在 HTML 里加个版本标识:




然后在 sw.js 里检测这个 meta 标签,版本变了就删旧缓存。

方案三:让用户感知更新

在 sw.js 里监听 updatefound,更新后提示用户刷新:

navigator.serviceWorker.addEventListener('controllerchange', () => {
window.location.reload();
});


配合 skipWaiting() 使用,效果更好。



我的建议:首页用 networkFirst 最稳妥,毕竟 HTML 体积小,网络请求一下也不亏,主要省心。你先改 sw.js 试试,改完记得在浏览器里 Application -> Service Workers 那里 Unregister 重新注册一下。
点赞
2026-03-16 15:05