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

如何使用Workbox缓存API响应实现断网时仍可展示历史数据

问题分析与解决方案

现有配置的问题

  • 策略选择不合理:当前查询类API使用CacheFirst策略,只要缓存存在就永远不会发起网络请求拉取最新数据,工单数据更新后用户无法获取到最新内容
  • 未区分POST接口类型:现有配置中所有匹配/\/api\/.*\/*.php/的POST请求都走NetworkOnly策略,完全不做缓存,如果你的工单查询接口是POST类型,断网时自然无法读取缓存
  • 无缓存过期规则:缓存会永久存储,长期使用会出现数据严重滞后、占用存储空间过多的问题

改造实现方案

根据你「优先从缓存读取数据,断网可正常展示」的需求,推荐使用StaleWhileRevalidate策略:优先返回缓存数据给前端,同时后台静默发起网络请求更新缓存,兼顾加载速度和数据时效性。如果需要优先展示最新数据、网络失败再降级读缓存,可以换成NetworkFirst策略。

改造后的配置代码

import {precacheAndRoute} from 'workbox-precaching';
import {clientsClaim, skipWaiting} from 'workbox-core';
import {registerRoute} from 'workbox-routing';
import {CacheFirst, NetworkFirst, NetworkOnly, StaleWhileRevalidate} from 'workbox-strategies';
import {CacheableResponsePlugin} from "workbox-cacheable-response";
import {BackgroundSyncPlugin} from 'workbox-background-sync';
import {Queue} from 'workbox-background-sync';
// 新增缓存过期插件
import {ExpirationPlugin} from 'workbox-expiration';


declare const self: ServiceWorkerGlobalScope;

skipWaiting();
clientsClaim();

const queue = new Queue('cola');

const bgSyncPlugin = new BackgroundSyncPlugin('api-cola', {
    onSync: async ({queue}) => {
    let entry;
    while ((entry = await queue.shiftRequest())) {
      try {
        let clone = entry.request.clone();
        await fetch(clone);
        console.error("Replay successful for request", entry.request);
      } catch (error) {
        console.error("Replay failed for request", entry.request, error);

        // Put the entry back in the queue and re-throw the error:
        await queue.unshiftRequest(entry);
        throw error;
      }
    }
    console.log("Replay complete!");
  }
});

// 注意:这个POST路由仅用于提交类请求(如新建工单、上传数据等),不要包含查询类POST接口
registerRoute(
  /\/api\/.*\/submit\/.*\.php/, // 建议调整匹配规则,只匹配提交类POST接口,不要覆盖查询类POST
  new NetworkOnly({
    plugins: [bgSyncPlugin]
  }),
  'POST'
);

// 处理GET类型的API查询请求
registerRoute(
  ({url}) => url.origin === 'https://xxx.xxx.com' &&
              url.pathname.startsWith('/api/'),
  new StaleWhileRevalidate({ // 替换为NetworkFirst可实现优先拉取最新数据,失败再读缓存
    cacheName: 'api-cache',
    plugins: [
      new CacheableResponsePlugin({
        statuses: [0, 200], // 去掉404,避免缓存错误响应
      }),
      // 新增缓存过期规则,最多存30天,最多缓存100条接口数据
      new ExpirationPlugin({
        maxAgeSeconds: 30 * 24 * 60 * 60,
        maxEntries: 100,
      })
    ]
  }),
  'GET' // 显式指定匹配GET请求
);

// 如果有POST类型的查询接口,单独添加规则
registerRoute(
  ({url, request}) => url.origin === 'https://xxx.xxx.com' &&
              url.pathname.startsWith('/api/workorder/list') && // 匹配工单查询接口路径
              request.method === 'POST',
  new StaleWhileRevalidate({
    cacheName: 'post-api-cache',
    plugins: [
      new CacheableResponsePlugin({
        statuses: [0, 200],
      }),
      new ExpirationPlugin({
        maxAgeSeconds: 7 * 24 * 60 * 60,
      })
    ]
  })
);

registerRoute(
  /assets\/images\/icons\/icon-.+\.png$/,
  new CacheFirst({
    cacheName: 'icons'
  })
);
precacheAndRoute(self.__WB_MANIFEST);

额外注意事项

  • 首次访问工单页面时需要有网络,接口返回成功后才会写入缓存,后续断网才能正常读取
  • 如果需要支持首次断网访问也有兜底内容,可以在前端代码中加降级逻辑:接口请求失败时读取本地存储的历史数据展示
  • 提交类POST接口不要设置缓存,避免重复提交或者读取到旧的提交状态

内容的提问来源于stack exchange,提问作者Rafa Alvarez-Ossorio Martin

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.11 23:09:02