Firefox无法识别新Service Worker,Chrome正常的技术求助
Firefox 110.0.1下PWA Service Worker无法触发更新问题
我正在使用Firefox 110.0.1版本将Web应用升级为PWA,目前遇到以下问题:
- Chrome中Service Worker首次安装正常,上传新版本时会提示用户,安装、激活及页面重载流程均正常,缓存修改也可生效,还能触发PWA安装提示;
- Firefox始终无法检测到Service Worker已更新,
updatefound监听器从未触发。
Service Worker代码
var staticCacheName = 'static'; var version = 'v1::90'; console.log("Hello there, this message is sent by a service worker " + version); self.addEventListener('install', function (event) { console.log("Service worker installed"); event.waitUntil(updateStaticCache()); }); //if the browser detects that this is a new service worker, our app js will tell this new sw to activate (via "// tell new service worker to register itself") self.addEventListener('message', (event) => { if (event.data === 'SKIP_WAITING') { console.log("skipWaiting 1"); self.skipWaiting(); console.log("skipWaiting 2"); } }); self.addEventListener('activate', function (event) { console.log("Service worker ACTIVATE"); event.waitUntil( caches.keys() .then(function (keys) { return Promise.all(keys .filter(function (key) { console.log("Cache version: " + key.indexOf(version)); return key.indexOf(version) !== 0; }) .map(function (key) { return caches.delete(key); }) ); }) ); }); function updateStaticCache() { console.log("updateStaticCache()"); return caches.open(version + staticCacheName) .then(function (cache) { return cache.addAll([ '/offlineScreen.html', '/js/js01.js', '/js/js02.js', '/imgs/songbookdb-PWA-icon-512.png', '/imgs/songbookdb-PWA-icon-192.png', '/imgs/icon-ios-512.png' ]); }); }; self.addEventListener('fetch', function (event) { console.log('Handling fetch event for', event.request.url); event.respondWith( caches.match(event.request).then(function (response) { if (response) { console.log('Found response in cache:', response); return response; } console.log('No response found in cache. About to fetch from network...'); return fetch(event.request).then(function (response) { console.log('Response from network is:', response); return response; }).catch(function (error) { console.error('Fetching failed:', error); return caches.match('/offlineScreen.html'); }); }) ); });
前端JS代码
window.addEventListener("DOMContentLoaded", async event => { function invokeServiceWorkerUpdateFlow(registration) { conf("There's an update for SongbookDB - Install now?", 'updateServiceWorker', registration); } // check if the browser supports serviceWorker at all if ('serviceWorker' in navigator) { console.log("service workers supported in browser"); // wait for the page to load window.addEventListener('load', async () => { // register the service worker from the file specified navigator.serviceWorker.register("/serviceWorker.js"); //const registration = await navigator.serviceWorker.register('/serviceWorker.js'); const registration = await navigator.serviceWorker.getRegistration(); if (registration) { console.log("service worker checks"); // ensure the case when the updatefound event was missed is also handled // by re-invoking the prompt when there's a waiting Service Worker if (registration.waiting) { // invokeServiceWorkerUpdateFlow(registration) } // detect Service Worker update available and wait for it to become installed registration.addEventListener('updatefound', () => { console.log("service worker update found"); if (registration.installing) { // wait until the new Service worker is actually installed (ready to take over) console.log("service worker installing"); registration.installing.addEventListener('statechange', () => { if (registration.waiting) { console.log("service worker waiting"); // if there's an existing controller (previous Service Worker), show the prompt if (navigator.serviceWorker.controller) { invokeServiceWorkerUpdateFlow(registration) } else { // otherwise it's the first install, nothing to do console.log('Service Worker initialized for the first time') } } }) } }) let refreshing = false; // detect controller change and refresh the page navigator.serviceWorker.addEventListener('controllerchange', () => { if (!refreshing) { window.location.reload() refreshing = true } }) // For prompting user to install let deferredPrompt; // This variable will save the event for later use. window.addEventListener('beforeinstallprompt', (e) => { console.log('install prompt'); // Prevents the default mini-infobar or install dialog from appearing on mobile //e.preventDefault(); // Save the event because you'll need to trigger it later. deferredPrompt = e; // Show your customized install prompt for your PWA // Your own UI doesn't have to be a single element, you // can have buttons in different locations, or wait to prompt // as part of a critical journey. //showInAppInstallPromotion(); }); } }) } function showResult(text) { //document.querySelector("output").innerHTML = text; console.log(text); } });
问题排查与修复建议
1. 修正Service Worker注册逻辑
当前代码中先调用register但不等待完成,直接用getRegistration()获取实例,Firefox中这个时机可能导致updatefound事件绑定不及时。
修复代码:
// 替换原注册相关代码 const registration = await navigator.serviceWorker.register('/serviceWorker.js'); // 移除navigator.serviceWorker.getRegistration()调用
2. 强制Firefox检查Service Worker更新
Firefox对Service Worker文件的缓存策略更严格,可能因旧文件缓存导致未触发更新:
- 服务器端给
serviceWorker.js设置缓存头:Cache-Control: no-cache, no-store, must-revalidate,避免浏览器缓存旧文件。 - 在页面加载时主动触发更新检测:
// 获取registration后添加 registration.update();
3. 确保Service Worker文件有字节级差异
Firefox要求新版本Service Worker必须和旧版本有字节级不同才能被识别为更新,修改version变量后要确保服务器上的文件已同步更新,且确实产生了内容变化。
4. 验证缓存清理逻辑
激活阶段的缓存过滤条件key.indexOf(version) !== 0要确保缓存名称拼接正确(version + staticCacheName),避免旧缓存未被清理导致后续异常。
内容的提问来源于stack exchange,提问作者Shaun
相关产品推荐
相关产品推荐

