From 33647f124f97a102160cad3e80d4e61981b5927f Mon Sep 17 00:00:00 2001 From: Anthony LC Date: Fri, 17 Oct 2025 15:14:04 +0200 Subject: [PATCH] =?UTF-8?q?=F0=9F=90=9B(service-worker)=20fix=20sw=20regis?= =?UTF-8?q?tration=20and=20page=20reload=20logic?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When a new service worker is installed, the page was reloaded to ensure the new service worker took control, it is not a big issue in normal browsing mode because the service worker is only updated once in a while (every release). However, in incognito mode, the service worker has to be re-registered on each new session, which means that the page was reloading each time the user opened a new incognito window, creating a bad user experience. We now take in consideration the case where the service-worker is installed for the first time, and don't reload if it is this case. --- CHANGELOG.md | 4 + .../service-worker/hooks/useSWRegister.tsx | 94 +++++++++++-------- 2 files changed, 60 insertions(+), 38 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 36dd3be15a..98a2734239 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,10 @@ and this project adheres to ## [Unreleased] +### Fixed + +🐛(service-worker) fix sw registration and page reload logic #1500 + ## [3.8.1] - 2025-10-17 ### Fixed diff --git a/src/frontend/apps/impress/src/features/service-worker/hooks/useSWRegister.tsx b/src/frontend/apps/impress/src/features/service-worker/hooks/useSWRegister.tsx index 998dab944c..5d21eace46 100644 --- a/src/frontend/apps/impress/src/features/service-worker/hooks/useSWRegister.tsx +++ b/src/frontend/apps/impress/src/features/service-worker/hooks/useSWRegister.tsx @@ -3,51 +3,69 @@ import { useEffect } from 'react'; export const useSWRegister = () => { useEffect(() => { if ( - 'serviceWorker' in navigator && - process.env.NEXT_PUBLIC_SW_DEACTIVATED !== 'true' + !('serviceWorker' in navigator) || + process.env.NEXT_PUBLIC_SW_DEACTIVATED === 'true' ) { - navigator.serviceWorker - .register(`/service-worker.js`) - .then((registration) => { - registration.onupdatefound = () => { - const newWorker = registration.installing; - if (!newWorker) { - return; - } + return; + } + + const hadControllerAtStart = !!navigator.serviceWorker.controller; - newWorker.onstatechange = () => { - if ( - newWorker.state === 'installed' && - navigator.serviceWorker.controller - ) { - newWorker.postMessage({ type: 'SKIP_WAITING' }); - } - }; + navigator.serviceWorker + .register(`/service-worker.js`) + .then((registration) => { + registration.onupdatefound = () => { + const newWorker = registration.installing; + if (!newWorker) { + return; + } + + newWorker.onstatechange = () => { + if ( + newWorker.state === 'installed' && + navigator.serviceWorker.controller + ) { + newWorker.postMessage({ type: 'SKIP_WAITING' }); + } }; - }) - .catch((err) => { - console.error('Service worker registration failed:', err); - }); - - let refreshing = false; - const onControllerChange = () => { - if (refreshing) { - return; - } - refreshing = true; + }; + }) + .catch((err) => { + console.error('Service worker registration failed:', err); + }); + + let refreshing = false; + const onControllerChange = () => { + if (!hadControllerAtStart || refreshing) { + return; + } + + refreshing = true; + + if (document.visibilityState === 'visible') { window.location.reload(); + return; + } + + const onVisible = () => { + if (document.visibilityState === 'visible') { + window.location.reload(); + } }; - navigator.serviceWorker.addEventListener( + + document.addEventListener('visibilitychange', onVisible, { once: true }); + }; + + navigator.serviceWorker.addEventListener( + 'controllerchange', + onControllerChange, + ); + + return () => { + navigator.serviceWorker.removeEventListener( 'controllerchange', onControllerChange, ); - - return () => { - navigator.serviceWorker.removeEventListener( - 'controllerchange', - onControllerChange, - ); - }; - } + }; }, []); };