Skip to content

Commit 4ff90ab

Browse files
committed
🐛(service-worker) force reload new service worker
When multiple tabs are open, the new service worker can stay in the "waiting" state and not be activated until the other tabs with the old service worker are closed. We fix this by forcing the other tabs to reload the page when a new service worker is detected. All tabs will then be reloaded and the new service worker will be activated.
1 parent 544dd00 commit 4ff90ab

File tree

3 files changed

+37
-0
lines changed

3 files changed

+37
-0
lines changed

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

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,16 +21,22 @@ describe('useSWRegister', () => {
2121
reject('error');
2222
}),
2323
);
24+
2425
Object.defineProperty(navigator, 'serviceWorker', {
2526
value: {
2627
register: registerSpy,
28+
addEventListener: jest.fn(),
2729
},
2830
writable: true,
2931
});
3032

3133
render(<TestComponent />);
3234

3335
expect(registerSpy).toHaveBeenCalledWith('/service-worker.js?v=123456');
36+
expect(navigator.serviceWorker.addEventListener).toHaveBeenCalledWith(
37+
'controllerchange',
38+
expect.any(Function),
39+
);
3440
});
3541

3642
it('checks service-worker is not register', () => {

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

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,33 @@ export const useSWRegister = () => {
88
) {
99
navigator.serviceWorker
1010
.register(`/service-worker.js?v=${process.env.NEXT_PUBLIC_BUILD_ID}`)
11+
.then((registration) => {
12+
registration.onupdatefound = () => {
13+
const newWorker = registration.installing;
14+
if (!newWorker) {
15+
return;
16+
}
17+
18+
newWorker.onstatechange = () => {
19+
if (
20+
newWorker.state === 'installed' &&
21+
navigator.serviceWorker.controller
22+
) {
23+
newWorker.postMessage({ type: 'SKIP_WAITING' });
24+
}
25+
};
26+
};
27+
})
1128
.catch((err) => {
1229
console.error('Service worker registration failed:', err);
1330
});
31+
32+
const currentController = navigator.serviceWorker.controller;
33+
navigator.serviceWorker.addEventListener('controllerchange', () => {
34+
if (currentController) {
35+
window.location.reload();
36+
}
37+
});
1438
}
1539
}, []);
1640
};

src/frontend/apps/impress/src/features/service-worker/service-worker.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,13 @@ self.addEventListener('install', function (event) {
6565
event.waitUntil(self.skipWaiting());
6666
});
6767

68+
self.addEventListener('message', (event) => {
69+
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
70+
if (event.data?.type === 'SKIP_WAITING') {
71+
void self.skipWaiting();
72+
}
73+
});
74+
6875
self.addEventListener('activate', function (event) {
6976
const cacheAllow = SW_VERSION;
7077

0 commit comments

Comments
 (0)