Webpack 4+Workbox Service Worker API缓存失效及请求缓慢问题
我之前也踩过类似的坑,用Workbox做API缓存不仅没享受到缓存的速度优势,反而出现了双重请求、耗时比直接请求还长的情况。结合你提到的Webpack3时代用GenerateSW完全正常的背景,咱们可以从这几个方向排查解决:
检查缓存策略的合理性
你现在是不是用了StaleWhileRevalidate这类默认会同时发起「缓存读取+网络请求」的策略?如果你的API响应是允许长期缓存的(比如有明确的Cache-Control头),换成CacheFirst策略能直接优先用缓存,避免不必要的网络请求。另外要注意,有没有配置多条重复匹配同一API路径的路由规则——规则重复会导致Workbox多次拦截处理请求,自然会出现双重请求。排查Service Worker的注册激活逻辑
对比你之前的配置,现在是不是没设置clientsClaim: true和skipWaiting: true?如果Service Worker激活后没有立刻接管所有客户端,可能会出现新旧SW同时处理请求的情况,引发双重请求。另外还要检查页面代码里有没有重复注册SW的逻辑,重复注册也会导致多个SW实例同时工作。核对Workbox与Webpack的版本兼容性
如果你升级了Webpack版本(比如从3升到4+),对应的Workbox-webpack-plugin版本是不是匹配?不同版本的Workbox在生成SW的逻辑上有不少变化,比如新版GenerateSW可能默认开启了预缓存或者额外的请求拦截特性,这些都可能导致请求被重复处理。建议你把现在的配置和Webpack3时代的旧配置逐条对比,关掉不需要的默认特性。分析开发者工具的请求详情
在Chrome DevTools的Network面板里,点开那两条重复的请求,看看Initiator列显示的发起者是谁——是页面直接发起的,还是Service Worker发起的?如果是页面先发起了请求,SW拦截后又发起了一次,那可能是页面初始化时没等SW激活就发请求了。这种情况可以在页面代码里加个逻辑,等SW注册激活完成后再发起API请求。避免混合使用不同的Workbox配置方式
你现在是不是同时用了GenerateSW和手动编写Service Worker代码(比如InjectManifest)?两种方式混用会导致SW逻辑重复,必然会出现双重请求的问题。建议只保留一种配置方式,比如继续用GenerateSW,并把API缓存的规则写在runtimeCaching里:
new workboxPlugin.GenerateSW({ swDest: 'sw.js', clientsClaim: true, skipWaiting: true, runtimeCaching: [ { urlPattern: /^https:\/\/your-api-domain\.com\/api/, handler: 'CacheFirst', options: { cacheName: 'api-cache', cacheableResponse: { statuses: [200], // 仅缓存成功响应 }, expiration: { maxAgeSeconds: 24 * 60 * 60, // 缓存有效期1天 }, }, }, ], });
按照上面的步骤逐一排查,应该能找到双重请求的根源,把缓存性能拉回之前的水平。
内容的提问来源于stack exchange,提问作者fiddlest

