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

Service Worker在Firebase Hosting无法返回/offline.html fallback页面求助

问题描述

Service Worker无法返回fallback页面(/offline.html),该问题仅在Firebase Hosting服务器环境中出现,本地主机下可正常返回。目前无报错,但控制台持续出现如下警告:

针对""的FetchEvent触发网络错误响应:重定向响应被用于重定向模式非"follow"的请求。

原代码

self.addEventListener("fetch", (evt) => {
  handleFetchIvent(evt);
});

function handleFetchIvent(evt) {
  if (evt.request.redirect == "follow") {
    console.log(evt.request.redirect);
    evt.respondWith(
      caches
        .match(evt.request)
        .then((cacheRes) => {
          return (
            cacheRes ||
            fetch(evt.request.url).then(
              async (fetchRes) => {
                // got a response from server

                const cache = await caches.open(dynamicCacheName);
                cache.put(evt.request.url, fetchRes.clone());

                // check cached items size
                limitCacheSize(dynamicCacheName, 5);
                return fetchRes;
              },
              (error) => {
                // network error
                return cache.match("/offline.html");
              }
            )
          );
        })
        .catch(() => {
          return caches.match("/offline.html");
        })
    );
  } // Change the redirect mode
  else if (
    evt.request.redirect == "manual" ||
    evt.request.redirect == "error"
  ) {
    const modRequest = new Request(evt.request, {
      redirect: "follow",
    });

    console.log(modRequest.redirect);
    evt.respondWith(
      caches
        .match(modRequest)
        .then((cacheRes) => {
          return (
            cacheRes ||
            fetch(modRequest.url).then(
              async (fetchRes) => {
                // got a response from server

                const cache = await caches.open(dynamicCacheName);
                cache.put(modRequest.url, fetchRes.clone());

                // check cached items size
                limitCacheSize(dynamicCacheName, 5);
                return fetchRes;
              },
              (error) => {
                // network error
                return cache.match("/offline.html");
              }
            )
          );
        })
        .catch(() => {
          return caches.match("/offline.html");
        })
    );
  }
}

问题分析与修复

Firebase Hosting会对部分请求(如不存在的资源)返回重定向响应,原代码存在两个核心问题:

  1. 分支处理非"follow"重定向请求时,用修改后的请求对象匹配缓存,但缓存中存储的是原始请求,导致匹配失败直接走网络请求;
  2. fetch仅传入URL而非完整请求对象,丢失了请求的上下文信息,在Firebase环境下易引发重定向相关的警告。

修改后的代码如下:

self.addEventListener("fetch", (evt) => {
  handleFetchEvent(evt);
});

function handleFetchEvent(evt) {
  let requestToUse = evt.request;

  // 统一将所有请求的重定向模式设为follow,消除警告
  if (evt.request.redirect !== "follow") {
    requestToUse = new Request(evt.request, { redirect: "follow" });
  }

  evt.respondWith(
    caches.match(requestToUse)
      .then(cacheRes => {
        // 缓存命中直接返回
        if (cacheRes) return cacheRes;

        // 缓存未命中则发起网络请求
        return fetch(requestToUse)
          .then(async fetchRes => {
            // 将响应存入动态缓存
            const cache = await caches.open(dynamicCacheName);
            cache.put(requestToUse, fetchRes.clone());
            limitCacheSize(dynamicCacheName, 5);
            return fetchRes;
          })
          .catch(() => {
            // 网络失败时返回离线页面
            return caches.match("/offline.html");
          });
      })
      .catch(() => {
        // 缓存匹配失败时返回离线页面
        return caches.match("/offline.html");
      })
  );
}

关键修改点

  • 简化逻辑:统一处理所有重定向模式的请求,无需分支判断;
  • 保留请求上下文:fetch使用完整请求对象而非仅URL,确保请求属性完整;
  • 强化失败处理:所有异常路径(网络错误、缓存匹配失败)都兜底返回离线页面。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 17:00:35