Service Worker删除缓存后存储占用未下降问题排查与解决
问题分析与解决方案
原因分析
两种缓存删除场景的核心差异在于Service Worker的生命周期状态:
- 版本更新+
skipWaiting时,旧Service Worker会被终止,新SW激活。此时旧缓存的所有引用被彻底释放,浏览器会立即回收对应的存储空间,所以Usage Storage正常下降。 - 消息指令删除缓存时,当前Service Worker仍处于活跃状态,即使调用
caches.delete()从Cache Storage中移除了缓存条目,SW可能还持有缓存的内部引用(比如之前caches.open()创建的缓存实例),浏览器无法立即回收这些空间。后续fetch事件触发时,SW会重新创建同名缓存并写入新内容,导致存储持续增长。
另外,浏览器的存储回收机制对活跃SW持有的资源会更保守,不会主动回收,直到SW被终止或空闲足够久。
解决办法
方案1:删除缓存后重启Service Worker
在message事件的缓存删除完成后,强制触发SW更新并激活新实例,彻底释放旧缓存的引用:
self.addEventListener('message', event => { if (event.data.type === 'delete-caches') { caches .keys() .then(keysList => { return Promise.all( keysList.map(key => { console.log(`[SW] Deleting Cache: ${key}`); return caches.delete(key); }) ); }) .then(() => { console.log('[SW] Caches Deleted'); // 触发SW更新并激活新实例 return self.registration.update(); }) .then(() => { return self.skipWaiting(); }) .then(() => { // 通知客户端刷新,确保新SW接管 self.clients.matchAll({ includeUncontrolled: true }).then(clients => { clients.forEach(client => { client.postMessage({ type: 'sw-restarted' }); }); }); }) .catch(err => { console.log('[SW] Deleting Caches Error: ', err); }); } });
客户端收到sw-restarted消息后,可以主动刷新页面,让新SW完全接管,此时旧SW被终止,浏览器会回收缓存空间。
方案2:模拟版本更新流程(更稳妥)
不直接删除当前活跃的缓存,而是通过切换版本号的方式,复用activate阶段的缓存清理逻辑:
- 在
message事件中,生成新的版本号(比如自增),并更新缓存名称。 - 触发SW更新,新SW安装时使用新版本号创建缓存。
- 新SW激活时,自动删除旧版本的缓存,同时旧SW被终止,空间正常回收。
修改后的核心代码示例:
// 初始版本,可通过message事件更新 let currentVersion = 0.01; let STATIC_CACHE_NAME = `static-v_${currentVersion}`; let DYNAMIC_CACHE_NAME = `dynamic-v_${currentVersion}`; // ... 其他生命周期代码不变 self.addEventListener('message', event => { if (event.data.type === 'delete-caches') { // 生成新版本号并更新缓存名称 currentVersion += 0.01; STATIC_CACHE_NAME = `static-v_${currentVersion}`; DYNAMIC_CACHE_NAME = `dynamic-v_${currentVersion}`; // 触发SW更新,新SW会使用新版本号 self.registration.update().then(() => { console.log('[SW] 触发版本更新,将在激活阶段清理旧缓存'); self.skipWaiting(); }); } });
这种方式完全复用了已验证有效的activate阶段缓存清理逻辑,避免了活跃SW持有缓存引用的问题,存储空间回收更可靠。
验证方式
执行缓存删除操作后:
- 查看DevTools的
Application > Cache Storage,确认所有缓存已被移除。 - 等待几秒或刷新页面后,查看
Application > Storage > Storage usage by origin,确认存储空间下降。 - 触发fetch事件,检查是否不会重复积累无效存储。
内容的提问来源于stack exchange,提问作者Manolis Thalassinos
相关产品推荐
相关产品推荐

