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

渐进式Web应用(PWA)无法加载已缓存静态资源问题求助

问题根因

你当前的Service Worker的fetch事件监听器仅处理了模式为navigate的导航类请求(仅覆盖页面跳转、首次加载页面这类场景),JS脚本、SVG、图标等静态资源的请求不属于navigate模式,没有触发任何缓存匹配逻辑,因此离线时无法返回已缓存的资源内容。

解决方案

修改fetch事件逻辑,增加静态资源的缓存匹配处理,修改后的参考代码如下:

const OFFLINE_VERSION = 1;
const CACHE_NAME = "offline";
const OFFLINE_URL = "offline.html";
const BASE = location.protocol + "//" + location.host;
const CACHED_FILES = [
  "https://cdn.jsdelivr.net/npm/kute.js@2.1.2/dist/kute.min.js",
  `${BASE}/src/favicon/favicon.ico`,
  `${BASE}/src/favicon/android-chrome-192x192.png`,
  `${BASE}/src/favicon/android-chrome-512x512.png`,
  `${BASE}/src/favicon/apple-touch-icon.png`,
  `${BASE}/src/favicon/favicon-16x16.png`,
  `${BASE}/src/favicon/favicon-32x32.png`,
  `${BASE}/src/svg/layered-waves.svg`,
  `${BASE}/js/background.js`,
  `${BASE}/js/animation-blob.js`
];

self.addEventListener('install', (event) => {
  event.waitUntil((async() => {
    const cache = await caches.open(CACHE_NAME);
    await Promise.all(
      [...CACHED_FILES, OFFLINE_URL].map((path) => {
        return cache.add(new Request(path, {cache: "reload", mode: 'cors'}));
      })
    );
  })());
  self.skipWaiting();
});

self.addEventListener('activate', (event) => {
  event.waitUntil((async () => {
    // 新增:清理旧版本缓存,避免冗余资源干扰
    const cacheKeys = await caches.keys();
    await Promise.all(
      cacheKeys.filter(key => key !== CACHE_NAME).map(key => caches.delete(key))
    );
    if ("navigationPreload" in self.registration) {
      await self.registration.navigationPreload.enable();
    }
  })());
  self.clients.claim();
});

self.addEventListener('fetch', (event) => {
  // 处理导航类请求:优先走网络,失败返回离线页
  if(event.request.mode === "navigate") {
    event.respondWith((async() => {
      try {
        const preloadResponse = await event.preloadResponse;
        if(preloadResponse) {
          return preloadResponse;
        }
        return await fetch(event.request);
      } catch(e) {
        const cache = await caches.open(CACHE_NAME);
        return await cache.match(OFFLINE_URL);
      }
    })());
    return;
  }

  // 处理静态资源请求:优先匹配缓存,缓存不存在走网络
  event.respondWith((async () => {
    const cache = await caches.open(CACHE_NAME);
    // 匹配缓存,ignoreSearch设为true可忽略请求后的查询参数
    const cachedRes = await cache.match(event.request, {ignoreSearch: true});
    if (cachedRes) {
      return cachedRes;
    }
    // 缓存不存在时尝试发起网络请求
    try {
      const networkRes = await fetch(event.request);
      // 可选:将新请求到的资源存入缓存,下次离线可直接使用
      // cache.put(event.request, networkRes.clone());
      return networkRes;
    } catch (e) {
      // 可根据资源类型返回对应占位内容,比如图片返回默认占位图
      return new Response('', {status: 404});
    }
  })());
});
补充说明
  • 代码中新增了activate阶段的旧缓存清理逻辑,更新Service Worker时会自动删除旧版本的缓存资源,避免冲突
  • 给跨域的CDN资源请求增加了mode: 'cors'配置,可解决部分跨域资源缓存失败的问题
  • 如果你的资源请求带有查询参数,cache.match的ignoreSearch参数会自动忽略参数完成匹配,你可根据实际需求调整

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.05 22:18:03