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

Workbox构建的Service Worker问题:302重定向失效及离线功能集成

解决Workbox Service Worker的两个问题:302重定向与离线页面/A2HS集成

嘿,我来帮你搞定这两个Workbox相关的问题,都是我之前踩过的坑,应该能直接帮到你!

1. 修复302重定向无法正常工作的问题

Workbox默认的缓存策略不会处理302重定向响应,因为它默认只缓存200状态码的资源。针对这个问题,有两种常见的解决方案,你可以根据自己的需求选择:

方案一:允许缓存302响应本身

如果你需要直接缓存302重定向响应(比如某些场景下需要保留重定向逻辑),可以在缓存策略中配置cacheableResponse插件,把302状态码加入允许缓存的列表:

workbox.routing.registerRoute(
  ({url}) => url.pathname.startsWith('/your-target-path'), // 匹配需要处理的请求路径
  new workbox.strategies.NetworkFirst({
    cacheName: 'redirect-cache',
    plugins: [
      new workbox.cacheableResponse.Plugin({
        statuses: [200, 302], // 包含302状态码
      }),
    ],
  }),
  'GET'
);

方案二:缓存重定向后的目标资源

大多数场景下,我们需要的是重定向后的实际资源,而不是302响应本身。这时可以自定义路由处理器,手动跟进重定向并缓存目标资源:

workbox.routing.registerRoute(
  ({url}) => url.pathname.startsWith('/your-redirect-source'),
  async ({event}) => {
    try {
      const response = await fetch(event.request);
      // 检查是否为302重定向
      if (response.status === 302) {
        const redirectUrl = new URL(response.headers.get('Location'), self.location.origin);
        // 请求重定向目标资源
        const redirectResponse = await fetch(redirectUrl);
        // 缓存目标资源到运行时缓存
        const cache = await caches.open(workbox.core.cacheNames.runtime);
        await cache.put(redirectUrl, redirectResponse.clone());
        return redirectResponse;
      }
      return response;
    } catch (error) {
      // 离线时返回备用页面(可选)
      return caches.match('/offline.html');
    }
  },
  'GET'
);

2. 集成Service Worker实现离线页面并触发「添加到主屏幕」提示

要满足A2HS(添加到主屏幕)的要求,你的应用需要符合PWA的核心标准,同时实现离线 fallback 逻辑。以下是分步实现方案:

步骤1:配置Manifest文件

首先创建manifest.json并放在根目录,包含A2HS要求的核心字段:

{
  "name": "你的应用全名",
  "short_name": "应用简称",
  "start_url": "/",
  "display": "standalone", // 独立应用模式,符合A2HS的体验要求
  "background_color": "#f0f0f0",
  "theme_color": "#2196F3",
  "icons": [
    {
      "src": "/icon-192x192.png",
      "sizes": "192x192",
      "type": "image/png"
    },
    {
      "src": "/icon-512x512.png",
      "sizes": "512x512",
      "type": "image/png"
    }
  ]
}

然后在主页面的<head>中引入:

<link rel="manifest" href="/manifest.json">

步骤2:预缓存离线页面

在Service Worker中使用Workbox的预缓存功能,确保离线页面在Service Worker安装时就被缓存:

// 预缓存离线页面及其他核心静态资源
workbox.precaching.precacheAndRoute([
  {url: '/offline.html', revision: 'v1'}, // 替换为你的离线页面路径,revision用于更新缓存
  // 可选:预缓存manifest.json、图标等资源
  {url: '/manifest.json', revision: 'v1'},
  {url: '/icon-192x192.png', revision: 'v1'}
]);

步骤3:设置全局离线Fallback

使用Workbox的setCatchHandler,当任何GET请求失败(比如离线时),自动返回离线页面:

// 全局离线 fallback 处理
workbox.routing.setCatchHandler(async ({event}) => {
  // 仅对HTML请求返回离线页面,其他资源(如CSS/JS)返回错误或自定义fallback
  if (event.request.destination === 'document') {
    return caches.match('/offline.html');
  }
  return Response.error();
});

步骤4:注册Service Worker

在主页面的JS中添加Service Worker注册代码,确保页面加载时注册:

if ('serviceWorker' in navigator) {
  window.addEventListener('load', async () => {
    try {
      const registration = await navigator.serviceWorker.register('/sw.js');
      console.log('Service Worker 注册成功:', registration);
    } catch (err) {
      console.error('Service Worker 注册失败:', err);
    }
  });
}

满足A2HS的额外注意事项

  • 你的站点需要使用HTTPS(本地开发的localhost除外)
  • 用户需要至少访问你的站点两次,且两次访问间隔不少于5分钟(浏览器默认的触发条件,无法通过代码修改)
  • 确保Service Worker处于激活状态,没有注册失败的情况

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.26 09:18:48