React搭配Workbox的Service Worker未缓存所有GET API请求如何解决
缓存问题分析与解决方案
现象原因
出现该现象的核心原因有两点:
- 当前Service Worker中自定义的
fetch事件仅实现了请求失败时回退读取缓存的逻辑,没有编写将请求成功的响应写入缓存的代码,因此默认不会自动存储接口的返回结果。 - Pokémon API返回的响应头配置了合法的缓存规则(存在
max-age等缓存有效字段),浏览器原生HTTP缓存会自动存储该响应,断网时可直接从原生缓存中读取返回;而另外两个随机数据接口的响应头配置了禁止缓存标识(Cache-Control为no-store/no-cache),浏览器原生缓存不会存储,因此断网时无法获取对应内容。
实现方案
要实现所有接口首次请求就缓存最新返回值,可选择以下两种方案,推荐优先使用Workbox内置规则,避免手动处理边界问题:
方案1:使用Workbox路由规则(推荐)
首先删除原有自定义的fetch事件监听代码,在Service Worker末尾新增以下代码即可:
// 匹配所有GET类型的API请求 registerRoute( ({ request }) => request.method === 'GET' && request.destination === '', // 采用先返回缓存同时后台更新缓存的策略,断网直接返回缓存内容 new StaleWhileRevalidate({ cacheName: 'api-cache', plugins: [ new ExpirationPlugin({ maxAgeSeconds: 7 * 24 * 60 * 60, // 缓存有效期可自定义,这里设为7天 maxEntries: 100, // 最多缓存100条接口响应,超出自动删除最早使用的缓存 }), ], }) );
方案2:修改原生fetch事件逻辑
如果不想使用Workbox规则,直接修改原有fetch事件代码,新增写入缓存的逻辑即可:
self.addEventListener('fetch', function (event) { // 仅处理GET请求,避免缓存POST等其他类型请求 if (event.request.method !== 'GET') return; event.respondWith( caches.open('api-cache').then(function(cache) { return fetch(event.request) .then(function(networkResponse) { // 请求成功时,克隆一份响应写入缓存 cache.put(event.request, networkResponse.clone()); return networkResponse; }) .catch(function() { // 断网时直接返回缓存中的对应响应 return cache.match(event.request); }); }) ); });
内容的提问来源于stack exchange,提问作者Hodl
相关产品推荐
相关产品推荐

