Cache API 缓存的资源怎么更新不生效?

若惜~ 阅读 3

我在 Service Worker 里用 Cache API 缓存了静态资源,但改了 JS 文件后刷新页面还是加载旧的,明明已经更新了版本号啊。

我试过在 install 事件里换新的缓存名,比如从 v1 改成 v2,也调用了 skipWaiting()clients.claim(),但有时候还是得手动清除缓存才生效,是不是哪里漏了?

self.addEventListener('install', event => {
  event.waitUntil(
    caches.open('my-cache-v2').then(cache => {
      return cache.addAll([
        '/index.html',
        '/app.js',
        '/style.css'
      ]);
    }).then(() => self.skipWaiting())
  );
});

self.addEventListener('fetch', event => {
  event.respondWith(
    caches.match(event.request).then(response => {
      return response || fetch(event.request);
    })
  );
});
我来解答 赞 3 收藏
二维码
手机扫码查看
1 条解答
司空法霞
我之前踩过这个坑,确实挺烦人的。你现在的代码逻辑基本是对的,但有个关键点容易被忽略:在 fetch 事件里需要先尝试网络请求再 fallback 到缓存。

试试把 fetch 事件改成这样:

self.addEventListener('fetch', event => {
event.respondWith(
fetch(event.request).then(response => {
if (!response || response.status !== 200 || response.type !== 'basic') {
return response;
}
let responseToCache = response.clone();
caches.open('my-cache-v2').then(cache => {
cache.put(event.request, responseToCache);
});
return response;
}).catch(() => {
return caches.match(event.request);
})
);
});


这样做的好处是每次都会优先尝试从网络获取最新资源,并且会自动更新缓存。记得要处理好异常情况,不然用户在网络不通时会看不到任何内容。

另外建议在 activate 事件里清理旧版本缓存:

self.addEventListener('activate', event => {
const cacheWhitelist = ['my-cache-v2'];
event.waitUntil(
caches.keys().then(cacheNames => {
return Promise.all(
cacheNames.map(cacheName => {
if (!cacheWhitelist.includes(cacheName)) {
return caches.delete(cacheName);
}
})
);
})
);
});


这个坑我踩过好几次了,希望能帮到你。服务工作者调试起来真不是一般的麻烦啊。
点赞
2026-03-31 12:18