如何检测React PWA是否运行最新版本并正确设置localStorage更新标记
问题根因
你当前代码里localStorage.setItem("updateAvailable", "false")的逻辑仅在首次注册Service Worker的场景下才会触发——只有用户第一次访问PWA、本地没有运行过旧Service Worker时,才会进入navigator.serviceWorker.controller为空的分支执行赋值。当用户已经运行过Service Worker、当前就是最新版本时,registration.onupdatefound事件根本不会触发,自然不会执行设为false的逻辑,之前遗留的true标记就会一直存在。
正确实现方案
你需要补充三个场景的标记处理逻辑:
- 页面初始化加载时先默认重置标记为false,避免旧标记残留
- 注册Service Worker时先检查是否已有等待激活的新版本,有则标记为true
- 监听Service Worker接管事件,新版本完成安装接管页面后自动重置标记为false
修改后参考代码:
// 页面初始化先重置更新标记,默认无可用更新 localStorage.setItem("updateAvailable", "false") function registerValidSW(swUrl: string, config?: Config) { console.log("test 5") navigator.serviceWorker .register(swUrl) .then(registration => { // 注册时先检查是否已有等待激活的新版本SW,有则直接标记可更新 if (registration.waiting) { localStorage.setItem("updateAvailable", "true") if (config && config.onUpdate) { config.onUpdate(registration); } } registration.onupdatefound = () => { const installingWorker = registration.installing; if (installingWorker == null) { return; } installingWorker.onstatechange = () => { if (installingWorker.state === 'installed') { if (navigator.serviceWorker.controller) { console.log( 'New content is available and will be used when all ' + 'tabs for this page are closed.' ); localStorage.setItem("updateAvailable", "true") if (config && config.onUpdate) { config.onUpdate(registration); } } else { console.log('Content is cached for offline use.'); localStorage.setItem("updateAvailable", "false") if (config && config.onSuccess) { config.onSuccess(registration); } } } }; }; }) .catch(error => { console.error('Error during service worker registration:', error); }); } // 监听新SW接管页面事件,重置更新标记 navigator.serviceWorker.addEventListener('controllerchange', () => { localStorage.setItem("updateAvailable", "false") // 可选:如果需要更新完成后立即刷新页面启用新内容,可放开下面注释 // window.location.reload() });
补充说明
如果你做了手动立即更新的功能,比如用户点击更新按钮后调用registration.waiting?.postMessage({ type: 'SKIP_WAITING' })触发SW跳过等待,更新完成后也会自动触发上面的controllerchange事件,不需要额外处理标记重置逻辑。
内容的提问来源于stack exchange,提问作者Maurice
相关产品推荐
相关产品推荐

