ServiceWorker仅重载缓存中已更改文件的异常问题排查
ServiceWorker预缓存更新异常问题解决
1. 安装阶段未等待异步缓存操作完成
你在install事件中直接循环调用cache.delete和cache.add,但这些都是异步Promise操作,ServiceWorker的install阶段不会自动等待所有异步任务完成,可能缓存还没更新完毕,install就已经结束,导致新资源并未真正被缓存。
需要用event.waitUntil包裹所有异步操作,并用Promise.all等待全部任务完成:
self.addEventListener('install', (event) => { event.waitUntil( caches.open('你的缓存名称').then((cache) => { // 批量执行删除操作 const deleteTasks = newFiles.map(resource => cache.delete(resource).catch(err => console.warn(`${resource}: ${err}`)) ); // 等待删除完成后,再批量添加新资源 return Promise.all(deleteTasks).then(() => { const addTasks = newFiles.map(resource => fetch(resource, { cache: 'reload' }).then(res => { if (!res.ok) throw new Error(`请求失败: ${resource}`); return cache.put(resource, res); }).catch(err => console.warn(`${resource}: ${err}`)) ); return Promise.all(addTasks); }); }) ); });
2. 浏览器HTTP缓存干扰
即使触发了ServiceWorker缓存更新,浏览器的磁盘缓存可能仍保留旧版main.css。cache.add()本质是发起网络请求,如果浏览器直接从本地HTTP缓存返回旧文件,ServiceWorker缓存的还是旧资源。
上面代码中使用fetch(resource, { cache: 'reload' }),强制浏览器绕过HTTP缓存,直接从服务器拉取最新资源,解决此问题。
3. 旧缓存版本未清理
如果缓存使用版本命名(如my-app-cache-v1),更新后需在activate阶段删除旧版本缓存,避免ServiceWorker误读取旧缓存中的资源:
self.addEventListener('activate', (event) => { const currentCache = '你的缓存名称-v2'; // 更新时修改版本号 event.waitUntil( Promise.all([ clients.claim(), caches.keys().then(cacheNames => { // 删除所有非当前版本的缓存 return Promise.all( cacheNames.filter(name => name !== currentCache) .map(name => caches.delete(name)) ); }) ]) ); });
4. 验证Fetch事件的缓存策略
确保你的fetch事件优先使用缓存中的最新资源,比如:
self.addEventListener('fetch', (event) => { event.respondWith( caches.match(event.request).then(cachedRes => { // 缓存存在则直接返回,否则请求网络 return cachedRes || fetch(event.request); }) ); });
若之前的策略是优先请求网络再缓存,可能导致旧资源被优先使用。
内容的提问来源于stack exchange,提问作者Jeff E Mandel
相关产品推荐
相关产品推荐

