Skip to content

Commit 33647f1

Browse files
committed
🐛(service-worker) fix sw registration and page reload logic
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.
1 parent e339cda commit 33647f1

File tree

2 files changed

+60
-38
lines changed

2 files changed

+60
-38
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@ and this project adheres to
66

77
## [Unreleased]
88

9+
### Fixed
10+
11+
🐛(service-worker) fix sw registration and page reload logic #1500
12+
913
## [3.8.1] - 2025-10-17
1014

1115
### Fixed

src/frontend/apps/impress/src/features/service-worker/hooks/useSWRegister.tsx

Lines changed: 56 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -3,51 +3,69 @@ import { useEffect } from 'react';
33
export const useSWRegister = () => {
44
useEffect(() => {
55
if (
6-
'serviceWorker' in navigator &&
7-
process.env.NEXT_PUBLIC_SW_DEACTIVATED !== 'true'
6+
!('serviceWorker' in navigator) ||
7+
process.env.NEXT_PUBLIC_SW_DEACTIVATED === 'true'
88
) {
9-
navigator.serviceWorker
10-
.register(`/service-worker.js`)
11-
.then((registration) => {
12-
registration.onupdatefound = () => {
13-
const newWorker = registration.installing;
14-
if (!newWorker) {
15-
return;
16-
}
9+
return;
10+
}
11+
12+
const hadControllerAtStart = !!navigator.serviceWorker.controller;
1713

18-
newWorker.onstatechange = () => {
19-
if (
20-
newWorker.state === 'installed' &&
21-
navigator.serviceWorker.controller
22-
) {
23-
newWorker.postMessage({ type: 'SKIP_WAITING' });
24-
}
25-
};
14+
navigator.serviceWorker
15+
.register(`/service-worker.js`)
16+
.then((registration) => {
17+
registration.onupdatefound = () => {
18+
const newWorker = registration.installing;
19+
if (!newWorker) {
20+
return;
21+
}
22+
23+
newWorker.onstatechange = () => {
24+
if (
25+
newWorker.state === 'installed' &&
26+
navigator.serviceWorker.controller
27+
) {
28+
newWorker.postMessage({ type: 'SKIP_WAITING' });
29+
}
2630
};
27-
})
28-
.catch((err) => {
29-
console.error('Service worker registration failed:', err);
30-
});
31-
32-
let refreshing = false;
33-
const onControllerChange = () => {
34-
if (refreshing) {
35-
return;
36-
}
37-
refreshing = true;
31+
};
32+
})
33+
.catch((err) => {
34+
console.error('Service worker registration failed:', err);
35+
});
36+
37+
let refreshing = false;
38+
const onControllerChange = () => {
39+
if (!hadControllerAtStart || refreshing) {
40+
return;
41+
}
42+
43+
refreshing = true;
44+
45+
if (document.visibilityState === 'visible') {
3846
window.location.reload();
47+
return;
48+
}
49+
50+
const onVisible = () => {
51+
if (document.visibilityState === 'visible') {
52+
window.location.reload();
53+
}
3954
};
40-
navigator.serviceWorker.addEventListener(
55+
56+
document.addEventListener('visibilitychange', onVisible, { once: true });
57+
};
58+
59+
navigator.serviceWorker.addEventListener(
60+
'controllerchange',
61+
onControllerChange,
62+
);
63+
64+
return () => {
65+
navigator.serviceWorker.removeEventListener(
4166
'controllerchange',
4267
onControllerChange,
4368
);
44-
45-
return () => {
46-
navigator.serviceWorker.removeEventListener(
47-
'controllerchange',
48-
onControllerChange,
49-
);
50-
};
51-
}
69+
};
5270
}, []);
5371
};

0 commit comments

Comments
 (0)