Vite React项目Service Worker静态资源缓存失效求助
解决Vite React应用Service Worker静态资源缓存失败问题
问题诊断
你的Service Worker install事件触发但资源未缓存,结合代码来看,主要存在以下几个核心问题:
cache.addAll未返回Promise:install事件中e.waitUntil需要等待缓存完成的Promise,但代码里cache.addAll(assets)没有return,导致SW可能在缓存操作完成前就提前激活。- Vite构建路径不匹配:生产环境下Vite会把
src目录下的文件打包成带hash的资源(比如assets/main.[hash].js),你缓存的/src/main.jsx这类源文件路径在构建后根本不存在。 - 跨域资源缓存错误:
https://fonts.gstatic.com是目录而非具体资源,cache.addAll无法缓存目录;同时跨域资源需要服务器返回CORS头才能被正常缓存。 - 缺少Fetch事件拦截逻辑:即使缓存成功,没有处理fetch事件的代码,浏览器会直接走网络请求,不会读取缓存内容。
- 激活事件未处理旧缓存:旧缓存可能干扰新缓存的生效,导致资源无法被正确读取。
修复后的Service Worker代码
const staticCacheName = 'site-static-v1'; // 加版本号方便更新缓存 // 注意:生产环境请替换为Vite构建后的实际资源路径,或用workbox自动生成 const assets = [ '/', '/index.html', '/manifest.json', // 示例:替换为Vite构建后的资源路径 // '/assets/main.[hash].js', // '/assets/App.[hash].css', '/icons/UP-72x72.png', '/icons/UP-96x96.png', '/icons/UP-128x128.png', '/icons/UP-144x144.png', '/icons/UP-152x152.png', '/icons/UP-192x192.png', '/icons/UP-384x384.png', '/icons/UP-512x512.png', '/screenshots/UP-screenshots-1280x890.png', '/screenshots/UP-screenshots-828x1792.png', 'https://fonts.googleapis.com/css2?family=Alata&family=Archivo+Black&family=Poppins:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;0,800;0,900;1,100;1,200;1,300;1,400;1,500;1,600;1,700;1,800;1,900&display=swap', // 示例:替换为具体字体文件URL // 'https://fonts.gstatic.com/s/alata/v10/PbytFmztEwbIoce9zq56BDmX.woff2', '/assets/react.svg', '/vite.svg', ]; self.addEventListener("push", e => { const data = e.data ? e.data.json() : {}; const title = data.title || "Default Title"; const options = { body: data.body || "You have a new message.", }; e.waitUntil(self.registration.showNotification(title, options)); }); self.addEventListener("install", e => { e.waitUntil( caches.open(staticCacheName).then(cache => { console.log("Caching static assets"); // 返回Promise确保waitUntil等待缓存完成 return cache.addAll(assets); }).catch(err => { console.error("缓存失败:", err); }) ); }); self.addEventListener("activate", e => { e.waitUntil( caches.keys().then(keys => { // 删除旧版本缓存 return Promise.all(keys.filter(key => key !== staticCacheName).map(key => caches.delete(key))); }) ); // 立即控制所有打开的页面 self.clients.claim(); }); self.addEventListener("fetch", e => { // 优先使用缓存,缓存不存在时请求网络 e.respondWith( caches.match(e.request).then(cachedResponse => { return cachedResponse || fetch(e.request); }) ); });
额外注意事项
- Vite生产构建路径:开发环境Vite使用源文件路径,但生产环境会打包到
dist目录,资源路径会变化。建议使用workbox-vite插件自动生成缓存清单,避免手动维护路径错误。 - 跨域资源处理:对于Google Fonts这类跨域资源,确保资源返回
Access-Control-Allow-Origin头,否则无法缓存。可以直接缓存CSS中引用的具体字体文件URL。 - 缓存版本管理:每次更新资源时,修改
staticCacheName的版本号(比如site-static-v2),确保SW触发更新并清理旧缓存。 - 调试技巧:在Chrome开发者工具的
Application > Cache Storage中查看缓存资源,确认是否成功缓存;在Service Workers面板查看SW状态和日志。
内容的提问来源于stack exchange,提问作者ipang
相关产品推荐
相关产品推荐

