Workbox Service worker Процесс обновления вручную
Это моя реализация в React Spa регистрации и обновления SW.
Проблема в том, что я запускаю ручное обновление текущего ПО и принимаю новую версию (например, отправляю сообщение SKIP WAITING
событие в активном ПО), и после активации нового ПО я не вижу controlling
событие запускается
import { useEffect, useRef } from 'react';
import { Workbox, messageSW } from 'workbox-window';
const SW_PATH = `${process.env.PUBLIC_PATH}sw.js`;
export const useSWRegisterOnMount = (param: {
createUIPrompt: (opts: { onAccept: () => void }) => void;
}): {
wb?: InstanceType<typeof Workbox>;
registration?: ServiceWorkerRegistration;
} => {
const history = useHistory();
const wb = useRef<InstanceType<typeof Workbox>>();
const registration = useRef<ServiceWorkerRegistration>();
useEffect(() => {
/** https://developers.google.com/web/tools/workbox/guides/advanced-recipes */
if ('serviceWorker' in navigator) {
wb.current = new Workbox(SW_PATH, {
scope: process.env.PUBLIC_PATH
});
const showSkipWaitingPrompt = (): void => {
param.createUIPrompt({
onAccept: () => {
// this works perfectly when app is reopened
// but in case of manual update service worker(workbox-window?) can skip emitting
// of this "controlling" (also "activate") event but sw get activated in devtools
// application sw panel
wb.current?.addEventListener('controlling', () => {
window.location.reload();
});
if (registration.current?.waiting) {
messageSW(registration.current.waiting, {
type: 'SKIP_WAITING'
});
}
}
});
};
wb.current.addEventListener('waiting', showSkipWaitingPrompt);
wb.current.addEventListener('externalwaiting', showSkipWaitingPrompt);
wb.current.register().then(swRegistration => {
registration.current = swRegistration;
});
// https://developers.google.com/web/fundamentals/primers/service-workers/lifecycle#manual_updates
setInterval(() => { // run manual updates
registration.current?.update().then(() => {
const sw = registration.current?.installing || registration.current?.waiting;
if (sw) {
showSkipWaitingPrompt();
}
});
}, 1000 * 60 * 60);
}
}, []);
return { wb: wb.current, registration: registration.current };
};
1 ответ
Вы должны обработать это событие на стороне работника службы:
addEventListener('message', (event) => {
if (event.data.type === 'SKIP_WAITING') {
skipWaiting();
}
});