You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Service Worker无法激活问题排查:缓存更新与事件触发异常

问题分析与解决方案

看起来你的Service Worker遇到了生命周期和事件处理的核心问题,我来逐一拆解并给出修复方案:


核心问题点

1. Service Worker激活事件仅在文件更新时触发

浏览器的Service Worker机制是:只有当serviceWorker.js文件内容发生实质性变化(哪怕是一行注释的修改)时,才会触发新的安装→激活流程。你当前的代码中,每次访问index.html注册的都是同一个未修改的serviceWorker.js,所以第二次及之后访问时,浏览器认为Worker已经处于激活状态,不会重复触发activate事件,自然不会执行缓存版本检查的逻辑。

2. fetch事件未正确使用event.respondWith()

你的fetch事件处理函数犯了一个关键错误:没有调用event.respondWith()来包裹响应逻辑。Service Worker对请求的拦截必须通过这个方法来返回自定义响应(缓存或网络请求),否则浏览器会默认中断请求,导致后续请求无响应。另外,cache变量仅在activate事件中初始化,如果activate没触发,cache会是undefined,执行cache.match()时会直接抛出错误,进一步破坏后续的fetch事件处理。

3. 缓存清理逻辑有误

你遍历缓存的方式caches.length并不是有效的API,正确获取所有缓存名称的方式是await caches.keys(),否则无法正确识别并删除旧缓存。


修复方案

步骤1:强制触发Service Worker更新检查

在页面注册Worker时,添加手动更新检查逻辑,确保每次页面加载时都检测是否有新版本:

window.addEventListener('load', async function(){
 if ( 'serviceWorker' in navigator ) {
 try{
 var registration=await navigator.serviceWorker.register('serviceWorker.js');
 // 监听更新事件
 registration.addEventListener('updatefound', () => {
   const newWorker = registration.installing;
   newWorker.addEventListener('statechange', () => {
     if (newWorker.state === 'installed') {
       if (navigator.serviceWorker.controller) {
         console.log('Nouvelle version disponible, rafraîchissez la page');
       }
     }
   });
 });
 // 手动触发更新检查
 await registration.update();
 console.log('ServiceWorker enregistré avec le scope: ', registration.scope);
 document.getElementById('worker').innerHTML='serviceWorker.js actif';
 document.getElementById('cache').innerHTML='Cache actif';
 }catch (err){
 console.log(err);
 }
 }else{window.alert('Votre navigateur ne supporte pas les Service Workers. Ce site ne fonctionnera pas en mode offline');};
});

步骤2:修正Service Worker的激活逻辑

修复缓存清理逻辑,并确保缓存名称在全局作用域存储:

let cacheName; // 全局存储当前缓存版本名称

self.addEventListener('install', event => {
 self.skipWaiting();
 console.log("ServiceWorker installé");
});

self.addEventListener('activate', async function(event){
 self.clients.claim();
 console.log("ServiceWorker activé");
 if (navigator.onLine){
   try {
     const oReq = new Request('version.txt?date='+new Date().getTime(), {method:'get'});
     const response = await fetch(oReq);
     cacheName = await response.text();
     console.log('Nouvelle version du cache: '+cacheName);
     // 获取所有缓存名称并清理旧缓存
     const existingCaches = await caches.keys();
     await Promise.all(
       existingCaches.map(cache => {
         if (cache !== cacheName) {
           return caches.delete(cache);
         }
       })
     );
     // 打开当前缓存并添加资源
     const cache = await caches.open(cacheName);
     await cache.addAll(['index.html','styles.css','traitement.js']);
   } catch (err) {
     console.log('Erreur lors de l\'activation:', err);
   }
 }
});

步骤3:修复fetch事件处理逻辑

必须用event.respondWith()包裹响应逻辑,同时处理缓存未初始化的情况:

self.addEventListener('fetch', function(event){
 console.log('Traitement du fetch '+event.request.url);
 if(event.request.url.includes('version.txt')){
   console.log('On laisse passer '+event.request.url);
   event.respondWith(fetch(event.request));
 }else{
   event.respondWith(
     (async function() {
       // 如果缓存未初始化,直接走网络请求
       if (!cacheName) {
         return fetch(event.request);
       }
       try{
         const cache = await caches.open(cacheName);
         const cachedResponse = await cache.match(event.request);
         if (cachedResponse){
           console.log('on sert '+event.request.url+' depuis le cache');
           return cachedResponse;
         }
         // 缓存无资源时走网络,可选:将新请求加入缓存
         const networkResponse = await fetch(event.request);
         await cache.put(event.request, networkResponse.clone());
         return networkResponse;
       }catch(err){
         console.log(event.request.url+' not cached or error:', err);
         // 离线且无缓存时返回错误提示
         return new Response('Erreur de chargement hors ligne', {status: 500});
       }
     })()
   );
 }
});

额外提示

  • 测试时,若要触发新的激活流程,可以在serviceWorker.js中添加一行无关注释(修改文件内容),这样浏览器会认为是新版本。
  • navigator.onLine的判断并不完全可靠,建议在网络请求失败时再降级到离线逻辑,而非仅依赖这个属性。

内容的提问来源于stack exchange,提问作者eddie

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 07:22:07