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

Vite+React SPA配置Workbox实现PWA离线自定义fallback页面失败求助

解决Vite-PWA离线时无法返回自定义offline.html的问题

问题根源

你遇到的核心问题是预缓存的index.html优先级高于Workbox的路由规则:默认情况下Vite-PWA会将SPA入口index.html加入预缓存列表,当离线时,所有导航类请求(request.mode === 'navigate')会直接命中预缓存的index.html,而非触发你配置的离线回退逻辑。

解决方案

以下提供两种可行的配置方案,根据你的使用场景选择即可:

方案一:使用generateSW模式(自动生成SW)

修改vite.config.ts中的PWA配置,重点是排除index.html的预缓存,让导航请求走自定义路由策略:

import { VitePWA } from 'vite-plugin-pwa';

export default {
  plugins: [
    VitePWA({
      workbox: {
        globPatterns: ['**/*.{png,svg,ico,txt,js,html,css}'],
        navigationPreload: true,
        // 确保offline.html被加入预缓存
        additionalManifestEntries: [
          { url: '/offline.html', revision: '1' }
        ],
        // 排除index.html的预缓存,强制导航请求走runtimeCaching
        exclude: ['index.html'],
        runtimeCaching: [
          {
            urlPattern: ({ request }) => request.mode === 'navigate',
            handler: 'NetworkFirst',
            options: {
              cacheName: 'navigation-cache',
              networkTimeoutSeconds: 1, // 快速判断网络是否不可用
              plugins: [
                {
                  handlerDidError: async () => {
                    // 网络失败时返回预缓存的offline.html
                    return caches.match('/offline.html');
                  }
                }
              ]
            }
          }
        ]
      }
    })
  ]
};

方案二:使用injectManifest模式(自定义SW)

如果需要更灵活的SW控制,改用自定义服务 Worker 文件:

  1. 编写src/sw.ts文件:
import { NetworkFirst } from 'workbox-strategies';
import { cleanupOutdatedCaches, precacheAndRoute, clientsClaim } from 'workbox-core';
import { registerRoute } from 'workbox-routing';
import { offlineFallback } from 'workbox-recipes';

declare let self: ServiceWorkerGlobalScope;

// 清理旧缓存
cleanupOutdatedCaches();
// 预缓存所有打包资源(包括offline.html)
precacheAndRoute(self.__WB_MANIFEST);

// 立即接管客户端
self.skipWaiting();
clientsClaim();

// 为导航请求配置网络优先策略
registerRoute(
  ({ request }) => request.mode === 'navigate',
  new NetworkFirst({
    cacheName: 'navigation-cache',
    networkTimeoutSeconds: 1,
  })
);

// 配置离线回退页面
offlineFallback({
  pageFallback: '/offline.html',
});
  1. 修改vite.config.ts切换到injectManifest模式:
import { VitePWA } from 'vite-plugin-pwa';

export default {
  plugins: [
    VitePWA({
      strategies: 'injectManifest',
      srcDir: 'src',
      filename: 'sw.ts',
      manifest: {
        // 你的Manifest配置(示例)
        name: 'My React PWA',
        short_name: 'React PWA',
        start_url: '/',
        display: 'standalone',
        background_color: '#fff',
        theme_color: '#41b883',
        icons: [
          {
            src: '/icon-192x192.png',
            sizes: '192x192',
            type: 'image/png'
          }
        ]
      },
      workbox: {
        globPatterns: ['**/*.{png,svg,ico,txt,js,html,css}'],
      }
    })
  ]
};

关键注意事项

  • 确保offline.html放在项目的public目录下,这样Vite会自动将其打包到dist根目录,且被Workbox纳入预缓存列表。
  • 测试前需清空旧的Service Worker缓存(Chrome DevTools → Application → Service Workers → Unregister),再重新构建并部署。
  • 离线测试可通过Chrome DevTools的Application → Service Workers勾选Offline选项验证。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 06:56:55