Service Worker缓存策略中,动态路由页面怎么总是返回旧内容?
我在用Vue Router做单页应用时,给Service Worker设置了缓存策略,静态资源没问题,但动态路由页面(比如/user/123)更新后,客户端还是返回旧内容。尝试过用url.pathname + location.search做cache key,也加了版本号,但访问/user/456新页面时控制台报错:GET https://example.com/user/456 net::ERR_CACHE_MISS,同时旧页面/user/123却一直读取缓存不更新。
这是我的sw.js配置片段:
const CACHE_PREFIX = 'v2:';
const staticCacheName = CACHE_PREFIX + 'static-resources';
const pageCacheName = CACHE_PREFIX + 'pages';
self.addEventListener('fetch', (event) => {
if (event.request.url.includes('/api')) return;
event.respondWith(
caches.match(event.request).then(cacheRes => cacheRes || fetchAndCache(event))
);
});
async function fetchAndCache(event) {
const response = await fetch(event.request);
await caches.open(pageCacheName).then(cache => cache.put(event.request, response.clone()));
return response;
}
难道动态路由的缓存需要单独处理?或者版本号更新后旧缓存没清除?
先说问题的根本原因:动态路由页面的 URL 是变化的,比如 /user/123 和 /user/456 都是不同的资源路径,Service Worker 会把它们当作完全不同的请求分别缓存。如果缓存没有及时更新或者旧缓存没清理,就会导致你访问新页面时读不到内容,而旧页面一直用老数据。
解决办法有几个关键点:
第一,确保每次应用版本更新时,清理掉旧的页面缓存。你可以监听 Service Worker 的 install 和 activate 事件,在 activate 时删除旧版本的缓存。比如这样写:
第二,动态路由页面的缓存策略需要调整。你现在的代码里,所有非 API 请求都会被缓存,但对于动态路由页面来说,这种策略可能会导致缓存污染。建议改为只缓存特定的静态页面(比如首页、登录页等),动态路由页面则每次都从网络获取最新内容,同时可以加一个 fallback 缓存作为兜底。修改 fetch 事件的逻辑:
第三,关于 ERR_CACHE_MISS 的问题,这是因为你在访问 /user/456 时,缓存里没有对应的资源,而你的代码又没有正确处理这种情况。上面的改动中,我加了一个 fallback 逻辑,当网络请求失败时尝试从缓存中读取,避免直接报错。
最后一个小建议,动态路由页面的内容通常依赖后端接口数据,所以更推荐的做法是只缓存静态资源,页面本身每次都从网络获取最新内容,然后通过接口数据来渲染。这样可以减少缓存管理的复杂度。
总之,核心思路就是:动态路由页面不要直接缓存,优先走网络请求;版本更新时清理旧缓存;加上 fallback 策略避免报错。按照这个思路改一下代码,应该就能解决问题了。