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

无框架PWA缓存更新问题:资源更新后无法重新生成缓存

解决PWA离线缓存更新后无法重新生成缓存的问题

核心问题分析

  1. Service Worker更新触发逻辑:浏览器仅当Service Worker(sw.js)文件本身有字节级变化时,才会触发更新流程。你当前用Date.now()生成缓存名,但如果sw.js代码没有实质改动,浏览器不会重新下载它,自然不会触发新的缓存生成。
  2. 缓存清理逻辑错误:activate事件里的!cacheName.includes(key)判断逻辑颠倒,导致无法正确删除旧缓存。
  3. 缺少SW激活控制:没有配置skipWaiting和clients.claim,新SW无法立即激活并接管页面,导致缓存更新不生效。

具体解决方案

1. 修改Service Worker代码(sw.js)

用版本号控制缓存名替代Date.now(),同时修复缓存清理逻辑、完善激活控制:

// 用版本号管理缓存,更新资源时手动升级版本号(比如v2→v3)
const cacheName = 'VSCode_SG_v2';
const assets = [
  './',
  './app.min.js',
  './favicon.ico',
  './style.css',
];

self.addEventListener('install', evt => {
  // 确保缓存全部添加完成后再结束install流程
  evt.waitUntil(
    caches.open(cacheName)
      .then(cache => cache.addAll(assets))
      .then(() => self.skipWaiting()) // 跳过等待,让新SW立即激活
  );
});

self.addEventListener('activate', evt => {
  evt.waitUntil(
    caches.keys().then(keys => {
      // 删除所有非当前版本的旧缓存
      return Promise.all(
        keys.map(key => {
          if (key !== cacheName) {
            return caches.delete(key);
          }
        })
      );
    }).then(() => self.clients.claim()) // 立即接管所有打开的页面
  );
});

self.addEventListener('fetch', evt => {
  evt.respondWith(
    caches.match(evt.request)
      .then(cacheRes => {
        // 优先返回缓存资源,缓存不存在则请求网络
        return cacheRes || fetch(evt.request);
      })
      .catch(err => console.error('Fetch error:', err))
  );
});

2. 修改Service Worker注册代码(app.js)

添加更新监听,确保用户能获取到最新的SW和缓存:

if ('serviceWorker' in navigator) {
  navigator.serviceWorker.register('./sw.js')
    .then(reg => {
      console.log('Service worker registered', reg);
      
      // 监听SW更新事件
      reg.addEventListener('updatefound', () => {
        const newWorker = reg.installing;
        newWorker.addEventListener('statechange', () => {
          if (newWorker.state === 'installed') {
            // 如果当前页面仍在使用旧SW,提示用户刷新
            if (navigator.serviceWorker.controller) {
              console.log('新版本已就绪,请刷新页面');
              // 这里可以添加UI提示,引导用户手动刷新
            }
          }
        });
      });
    })
    .catch(err => console.log('Service worker not registered', err));

  // 当新SW激活后,自动刷新页面
  navigator.serviceWorker.addEventListener('controllerchange', () => {
    window.location.reload();
  });
}

关键操作说明

  • 更新资源时的操作:每次修改静态资源(如app.min.js、style.css)后,手动修改sw.js里的cacheName版本号(比如从v2改成v3),浏览器会检测到sw.js的变化,自动触发SW更新流程,重新生成缓存。
  • 开发者工具调试:在Chrome开发者工具的Application > Service Workers中,勾选Update on reload,可以强制在页面刷新时检查SW更新,方便开发调试。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.21 19:24:27