You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PWA缓存异常:Chrome缓存占用达500MB,请求排查原因及解决方法

聊聊你的PWA在Chrome里缓存飙到500MB的问题

我之前帮朋友排查过类似的PWA缓存膨胀问题,结合你的描述,大概率是这几个原因导致的,咱们一步步拆解:

可能的诱因

1. 动态缓存没做任何限制,啥都往里塞

你用的「优先缓存,回退网络」策略,如果fetch事件里没做过滤,只要是网络返回的资源就往DYNAMIC_CACHEABLE_ASSETS里加,那麻烦就来了——比如用户反复打开的高清大图、接口返回的超大JSON数据,甚至不小心缓存了POST请求的响应(比如带大文件上传的返回),这些都会疯狂占空间。而且安卓设备系统层面有缓存上限,会自动清理溢出的部分,但Chrome桌面版默认缓存配额高很多,不会主动清,所以差距就出来了。

2. 旧缓存版本没清理,越积越多

你有没有在activate事件里处理旧缓存?如果每次部署更新了STATIC_CACHE_VERSION,但没删掉旧的静态缓存,那每次上线都会新增一份缓存,旧的还留在那。另外,serviceworker-webpack-plugin生成的serviceWorkerOption.assets会不会偷偷包含了source map文件?这些文件体积超大,要是被缓存了,分分钟占几十上百MB。

3. fetch逻辑没过滤不必要的请求

比如你是不是把第三方资源(比如广告图、统计脚本)也缓存了?或者没过滤大文件(比如视频、压缩包)?这些资源本来就不该进缓存,要是不小心加进去了,缓存大小肯定会爆炸。

4. 别被Chrome DevTools的显示坑了

虽然概率不大,但可以确认下DevTools里的「Cache Storage」是不是只展示了你应用域名下的缓存,有时候会混进其他站点的缓存数据,不过你安卓端只有20MB,这个可能性比较低。

对应的解决办法

给动态缓存加“刹车”:大小限制+过期清理

写个简单的缓存修剪函数,每次加新资源前检查总大小,超过阈值就删掉最老的条目:

const DYNAMIC_CACHE_MAX_SIZE = 50 * 1024 * 1024; // 设个50MB上限

function trimDynamicCache(cacheName, maxSize) {
  caches.open(cacheName).then(cache => {
    cache.keys().then(keys => {
      if (keys.length > maxSize) {
        // 删除最旧的缓存,递归直到符合大小限制
        cache.delete(keys[0]).then(() => trimDynamicCache(cacheName, maxSize));
      }
    });
  });
}

然后在fetch事件里,把资源加入缓存后调用这个函数。同时,只缓存GET请求,POST/PUT这些非幂等请求的响应绝对不能缓存,还要过滤掉大文件(比如后缀是.mp4/.zip的)。

在activate事件里彻底清理旧缓存

每次Service Worker激活时,删掉所有和当前版本不匹配的缓存:

self.addEventListener('activate', event => {
  event.waitUntil(
    caches.keys().then(cacheNames => {
      return Promise.all(
        cacheNames.filter(name => {
          // 保留当前静态缓存和动态缓存,其他全删
          return name !== STATIC_CACHE_VERSION && name !== DYNAMIC_CACHEABLE_ASSETS;
        }).map(oldCache => caches.delete(oldCache))
      );
    })
  );
});

记得每次静态资源更新时,一定要修改STATIC_CACHE_VERSION的值(比如从static-v1改成static-v2),这样激活事件才会触发清理。

严格过滤要缓存的资源

在fetch事件开头加几道关卡,只让必要的资源进缓存:

self.addEventListener('fetch', event => {
  // 跳过非GET请求
  if (event.request.method !== 'GET') return;
  // 跳过第三方资源(如果不需要缓存的话)
  if (!event.request.url.startsWith(self.location.origin)) return;
  // 跳过大文件类型
  const forbiddenExtensions = ['.mp4', '.zip', '.tar'];
  if (forbiddenExtensions.some(ext => event.request.url.includes(ext))) return;

  // 你的缓存逻辑
  event.respondWith(
    caches.match(event.request).then(cachedRes => {
      const fetchRes = fetch(event.request).then(networkRes => {
        caches.open(DYNAMIC_CACHEABLE_ASSETS).then(cache => {
          cache.put(event.request, networkRes.clone());
          trimDynamicCache(DYNAMIC_CACHEABLE_ASSETS, DYNAMIC_CACHE_MAX_SIZE);
        });
        return networkRes;
      });
      return cachedRes || fetchRes;
    })
  );
});

检查serviceWorkerOption.assets里的资源

在sw.js的install事件里加个打印,看看serviceWorkerOption.assets到底包含了啥:

console.log('[sw] 即将缓存的静态资源:', serviceWorkerOption.assets);

要是发现有source map或者其他超大文件,就在webpack的serviceworker-webpack-plugin配置里用exclude选项把它们排除掉,别让这些冗余资源占缓存。

最后,你可以打开Chrome DevTools的「Application」→「Cache Storage」,挨个查看缓存条目大小,找到占空间最大的那个,这样就能精准定位问题根源了。

内容的提问来源于stack exchange,提问作者amdev

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 09:05:16