Service Worker缓存策略中,动态路由页面怎么总是返回旧内容?

程序猿东硕 阅读 17

我在用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;
}

难道动态路由的缓存需要单独处理?或者版本号更新后旧缓存没清除?

我来解答 赞 5 收藏
二维码
手机扫码查看
1 条解答
码农玉鑫
这个问题的核心在于动态路由页面的缓存策略和版本控制。你现在的代码逻辑中,动态路由页面(比如 /user/123)会被当成独立的请求缓存起来,但没有处理好缓存更新和清理的问题。

先说问题的根本原因:动态路由页面的 URL 是变化的,比如 /user/123 和 /user/456 都是不同的资源路径,Service Worker 会把它们当作完全不同的请求分别缓存。如果缓存没有及时更新或者旧缓存没清理,就会导致你访问新页面时读不到内容,而旧页面一直用老数据。

解决办法有几个关键点:

第一,确保每次应用版本更新时,清理掉旧的页面缓存。你可以监听 Service Worker 的 install 和 activate 事件,在 activate 时删除旧版本的缓存。比如这样写:

self.addEventListener('activate', (event) => {
event.waitUntil(
caches.keys().then(keys => {
return Promise.all(keys.map(key => {
if (!key.startsWith(CACHE_PREFIX)) {
return caches.delete(key);
}
}));
})
);
});


第二,动态路由页面的缓存策略需要调整。你现在的代码里,所有非 API 请求都会被缓存,但对于动态路由页面来说,这种策略可能会导致缓存污染。建议改为只缓存特定的静态页面(比如首页、登录页等),动态路由页面则每次都从网络获取最新内容,同时可以加一个 fallback 缓存作为兜底。修改 fetch 事件的逻辑:

self.addEventListener('fetch', (event) => {
if (event.request.url.includes('/api')) return;

const url = new URL(event.request.url);
// 对于动态路由页面,优先从网络获取
if (url.pathname.startsWith('/user/')) {
event.respondWith(
fetch(event.request).catch(() => caches.match(event.request))
);
return;
}

// 其他页面走原来的缓存逻辑
event.respondWith(
caches.match(event.request).then(cacheRes => cacheRes || fetchAndCache(event))
);
});


第三,关于 ERR_CACHE_MISS 的问题,这是因为你在访问 /user/456 时,缓存里没有对应的资源,而你的代码又没有正确处理这种情况。上面的改动中,我加了一个 fallback 逻辑,当网络请求失败时尝试从缓存中读取,避免直接报错。

最后一个小建议,动态路由页面的内容通常依赖后端接口数据,所以更推荐的做法是只缓存静态资源,页面本身每次都从网络获取最新内容,然后通过接口数据来渲染。这样可以减少缓存管理的复杂度。

总之,核心思路就是:动态路由页面不要直接缓存,优先走网络请求;版本更新时清理旧缓存;加上 fallback 策略避免报错。按照这个思路改一下代码,应该就能解决问题了。
点赞 3
2026-02-14 23:01