配置Workbox缓存newsapi.org资源后,离线访问提示无缓存响应
嗨,我来帮你捋捋这个问题!你说按照Vaadin PWA教程配置了Workbox路由,能看到newsapi.org的文章已经存在缓存里,但Chrome切到离线模式后访问,Workbox却提示找不到响应——我猜问题大概率出在跨域请求的缓存处理逻辑上,给你拆解下原因和修复方案:
先贴出你当前的代码方便对照:
workbox.routing.registerRoute( // Cache news articles new RegExp('^https?://newsapi.org/(.*)'), args => { return workbox.strategies.networkFirst({ cacheName: 'news-cache', plugins: [ new workbox.expiration.Plugin({ maxEntries: 20, maxAgeSeconds: 7 * 24 * 60 * 60, }), ], }).handle(args).then(response => { if (!response) { return caches.match('./fallback.json'); } return response; }); });
你遇到的错误截图:
核心问题分析
你现在的写法是把策略的handle方法放在路由回调里手动处理,这种方式绕开了Workbox内部的缓存匹配逻辑。尤其是跨域请求(newsapi.org是第三方域名),浏览器处理跨域成功响应的状态码是0而非常规的200,默认情况下Workbox不会缓存状态码非2xx的响应——哪怕你看到缓存里有资源,离线时也可能因为键不匹配或者策略逻辑没正确触发,导致找不到响应。
具体修复方案
方案1:改用Workbox标准的路由注册方式(最推荐)
直接把策略实例传给registerRoute,不要手动调用handle,同时加上cacheableResponse插件来允许缓存跨域响应:
workbox.routing.registerRoute( // 匹配newsapi的所有请求 new RegExp('^https?://newsapi.org/(.*)'), // 使用networkFirst策略,同时配置必要插件 new workbox.strategies.networkFirst({ cacheName: 'news-cache', plugins: [ new workbox.expiration.Plugin({ maxEntries: 20, maxAgeSeconds: 7 * 24 * 60 * 60, // 7天有效期 }), // 关键:允许缓存状态码为0(跨域成功)和200的响应 new workbox.cacheableResponse.Plugin({ statuses: [0, 200], }), ], }), ); // 单独处理全局的fallback逻辑,更清晰 workbox.routing.setCatchHandler(async ({ event }) => { // 如果是文档请求,返回fallback.json if (event.request.destination === 'document') { return caches.match('./fallback.json'); } // 其他请求返回错误 return Response.error(); });
方案2:检查缓存键的一致性
打开Chrome DevTools的Application > Cache Storage > news-cache,查看缓存的资源键是不是和你离线时请求的URL完全一致。比如缓存里的键是https://newsapi.org/v2/top-headlines?country=us,你离线请求的是不是完全相同的URL?有没有参数、协议(http/https)的差异?
方案3:验证响应头的缓存许可
虽然你已经看到缓存里有资源,但可以检查下newsapi返回的响应头里有没有Cache-Control头,确保浏览器允许缓存该资源。比如响应头里有Cache-Control: public, max-age=3600这类配置,会让缓存更可靠。
最后记得:更新Service Worker后,在Chrome里点击Application > Service Workers > Update,清空旧的缓存(Application > Storage > Clear site data),然后重新测试离线模式!
内容的提问来源于stack exchange,提问作者Simon Shaw

