PWA离线缓存为啥不生效?

打工人世豪 阅读 11

我用 Workbox 配置了 PWA 的离线缓存,但刷新页面还是提示没网就打不开,缓存好像根本没起作用。

我在 sw.js 里用了 registerRoute 缓存 HTML 和静态资源,也确认 service worker 注册成功了。Network 面板里看到请求还是走网络,离线时直接挂掉。

这是我的 service worker 配置:

import { registerRoute } from 'workbox-routing';
import { NetworkFirst, CacheFirst } from 'workbox-strategies';

registerRoute(
  ({ request }) => request.destination === 'document',
  new NetworkFirst({ cacheName: 'pages' })
);

registerRoute(
  ({ request }) => request.destination === 'script' || request.destination === 'style',
  new CacheFirst({ cacheName: 'assets' })
);

是不是策略用错了?还是说 HTML 不能这么缓存?

我来解答 赞 1 收藏
二维码
手机扫码查看
1 条解答
极客静依
你的问题很典型,PWA离线缓存不生效多半是几个常见原因造成的。首先检查下你的缓存策略,用NetworkFirst缓存HTML确实容易翻车,因为这个策略会优先尝试网络请求,失败才会用缓存。

我建议HTML改用StaleWhileRevalidate策略,这样能确保优先使用缓存同时后台更新:

registerRoute(
({ request }) => request.destination === 'document',
new StaleWhileRevalidate({ cacheName: 'pages' })
);


另外还有几个坑要注意:
1. 确保sw.js放在项目根目录,scope才能覆盖整个站点
2. 检查浏览器兼容,iOS的PWA支持就是个玄学
3. 清除旧缓存试试,有时候是被旧缓存干扰了
4. 在Chrome的Application面板里检查Cache Storage,看缓存是否真的存进去了

如果还不行,可以在sw.js里加个fetch事件监听器手动处理:

self.addEventListener('fetch', (event) => {
event.respondWith(
caches.match(event.request).then(response => {
return response || fetch(event.request);
})
);
});


这种问题我见多了,有时候Workbox的抽象层反而会隐藏底层细节。实在不行就先不用Workbox,裸写service worker更直观。
点赞
2026-03-09 11:00