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

PHP网站Service Worker实现:网络优先缓存+静态页降级方案咨询

实现「优先网络、失败读缓存、降级静态页」的Service Worker逻辑

嘿,你已经完成了Service Worker的注册和基础缓存命名,接下来咱们把目标逻辑落地成可运行的代码,我会尽量把每一步讲明白,帮你理解Promise的链式流程:

核心Fetch事件拦截逻辑

在你的sw.js里添加以下代码,这是实现需求的核心:

// 先定义降级用的离线页面路径,你可以根据自己的实际页面调整
const FALLBACK_PAGE = '/offline.html';

self.addEventListener('fetch', (event) => {
  event.respondWith(
    // 第一步:优先尝试网络请求
    fetch(event.request)
      .then((networkResponse) => {
        // 如果网络请求成功,把响应存入动态缓存(可选,但能提升后续离线体验)
        caches.open(CACHE_DYNAMIC_NAME).then((cache) => {
          cache.put(event.request, networkResponse.clone());
        });
        // 返回网络响应给页面
        return networkResponse;
      })
      .catch(() => {
        // 第二步:网络失败,尝试从静态缓存中读取请求
        return caches.match(event.request)
          .then((cachedResponse) => {
            // 如果静态缓存有对应资源,返回它
            if (cachedResponse) {
              return cachedResponse;
            }
            // 第三步:缓存也没有,返回降级的离线页面
            return caches.match(FALLBACK_PAGE);
          });
      })
  );
});

关键细节解释

  • 优先网络策略:我们先调用fetch(event.request)发起网络请求,这是最优先的逻辑,确保用户能拿到最新内容。
  • 缓存更新:网络请求成功后,把响应克隆一份存入动态缓存(注意要clone(),因为响应流只能被消费一次),这样下次离线时就能用最新的缓存内容了。
  • 降级链路:如果网络请求失败(catch块触发),先去静态缓存里找有没有匹配的资源;要是静态缓存也没找到,就返回你预先定义的离线页面,保证用户不会看到浏览器默认的错误页。

额外注意事项

  • 别忘了把你的降级离线页面(比如offline.html)加入到静态缓存的预缓存列表里!不然缓存里找不到这个页面,最后一步也会失败。比如在SW的install事件里添加:
    self.addEventListener('install', (event) => {
      event.waitUntil(
        caches.open(CACHE_STATIC_NAME)
          .then((cache) => {
            // 这里添加你要预缓存的静态资源,包括降级页面
            return cache.addAll([
              '/',
              '/index.php',
              '/offline.html',
              // 其他静态资源比如CSS、JS、图片等
            ]);
          })
      );
    });
    
  • 缓存版本号(比如你的static-v74)更新时,记得在activate事件里清理旧缓存,避免冗余缓存占用空间:
    self.addEventListener('activate', (event) => {
      event.waitUntil(
        caches.keys().then((cacheNames) => {
          return Promise.all(
            cacheNames.filter((cacheName) => {
              // 过滤掉旧的静态缓存(这里根据你的命名规则调整)
              return cacheName.startsWith('static-') && cacheName !== CACHE_STATIC_NAME;
            }).map((cacheName) => {
              return caches.delete(cacheName);
            })
          );
        })
      );
    });
    

这样一套逻辑下来,就能完美实现你要的「优先网络→缓存兜底→静态页降级」的离线体验了,要是有哪块没搞懂,随时问!

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.26 09:17:37