Несогласованное поведение с workbox-window.update()
Платформа
"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.70 Safari/537.36"
Версия Workbox
5.0.0-rc.0
Я использую окно рабочего окна update()
для запуска проверки обновлений сервис-воркера, как описано в проблеме с рабочим ящиком № 2130. Этот вопрос также, кажется, связан с наблюдениями, сделанными в выпуске № 2301 рабочего ящика.
<script type="module">
import {Workbox} from 'https://storage.googleapis.com/workbox-cdn/releases/5.0.0-rc.0/workbox-window.prod.mjs';
if ('serviceWorker' in navigator) {
const wb = new Workbox('/sw.js');
// Grab the update button from the UI using jQuery and add a listener to it.
$('#update-button').on('click', function () {
wb.update();
});
....
}
</script>
Если обнаружено обновление, загружается новый сервисный работник и переходит в состояние ожидания. Я слушаю это событие (обаwaiting
а такжеexternalwaiting
, делая то же самое в обоих случаях) и спросите пользователя, хотят ли они установить обновление сейчас или позже.
function handleWaiting(wb) {
if (confirm("An update is available for this app. Install now?")) {
wb.messageSW({type: 'SKIP_WAITING'});
}
}
wb.addEventListener('waiting', event => {
handleWaiting(wb);
});
wb.addEventListener('externalwaiting', event => {
handleWaiting(wb);
});
В большинстве случаевwaiting
событие запускается, и если пользователь принимает обновление, сервисный работник активируется, и мы можем перезагрузить страницу, чтобы завершить процесс обновления:
function handleActivated(wb, event) {
if (event.isUpdate) {
window.location.reload();
} else {
wb.messageSW({ type: 'CLIENTS_CLAIM' });
}
}
wb.addEventListener('activated', event => {
handleActivated(wb, event);
});
wb.addEventListener('externalactivated', event => {
handleActivated(wb, event);
});
Еслиwaiting
событие запускается, этот процесс работает нормально.
- Внесите небольшое обновление в приложение, которое приведет к изменению файла сервис-воркера.
- Нажмите кнопку "Проверить наличие обновлений".
- Найден новый сервисный работник, и пользователю предлагается установить обновление
- Страница перезагружена.
Но еслиexternalwaiting
событие запускается, то этот код не работает. Новый работник службы остается в состоянии ожидания, что я вижу в Chrome Dev Tools.
Пропустить ожидающее сообщение, полученное старым сервис-воркером
Если пользователь подтверждает, что хочет обновить SKIP_WAITING
сообщение получено более старым активированным определением работника службы.
Вот выдержка из моих журналов, подтверждающая это.
- Записи журнала со стороны приложения / клиента имеют префикс "Приложение", за которым следует версия приложения.
- Записи журнала работника службы имеют префикс "Service Worker", за которым следует дата DOB, уникальная для каждого экземпляра Service Worker.
01 [Application 0.0.1.2019.11.05-48] Checking for updates...
02 [Service Worker 2019-11-05 @ 15:23:14] <<<<<<<<<<<<<<< STARTING >>>>>>>>>>>>>>>
03 [Service Worker 2019-11-05 @ 15:23:14] Yay! Workbox 5.0.0-rc.0 is loaded
04 [Service Worker 2019-11-05 @ 15:23:14] Lifecycle event: [install]
05 [Application 0.0.1.2019.11.05-48] Service Worker lifecycle event: 06 [externalinstalled]
07 [Application 0.0.1.2019.11.05-48] Service Worker lifecycle event: [externalwaiting]
08 [Application 0.0.1.2019.11.05-48] handle waiting...
09 [Service Worker 2019-11-05 @ 15:20:03] Message event: [SKIP_WAITING]
В сети
- Пользователь только что нажал кнопку "Проверить наличие обновлений".
- На сайте обнаружена новая версия сервис-воркера.
2019-11-05 @ 15:23:14
и разбирается. Мы назовем это SWv2. - Workbox загружен SWv2.
- SWv2
install
обработчик событий выполняется. - Окно Workbox
externalinstalled
обработчик событий выполняется. - Окно Workbox
externalwaiting
обработчик событий выполняется. - Окно рабочего окна
externalwaiting
обработчик событий отправляетSKIP_WAITING
сообщение с использованиемworkboxWindow.messageSW()
- Service Worker v1 (загружается на
2019-11-05 @ 15:20:03
) получает сообщение об ожидании пропуска. Ничего не произошло. SWv2 остается в состоянии ожидания.
В отличие от обычного события ожидания
В следующем журнале вы можете увидеть, что SKIP_WAITING
сообщение получено ожидающим работником службы: v2019-11-05 @ 16:07:32
. Таким образом, процесс обновления завершается успешно.
[Application 0.0.1.2019.11.05-52] Checking for updates...
[Service Worker 2019-11-05 @ 16:07:32] <<<<<<<<<<<<<<< STARTING >>>>>>>>>>>>>>>
[Service Worker 2019-11-05 @ 16:07:32] Yay! Workbox 5.0.0-rc.0 is loaded
[Service Worker 2019-11-05 @ 16:07:32] Lifecycle event: [install]
[Application 0.0.1.2019.11.05-52] Service Worker lifecycle event: [installed]
[Application 0.0.1.2019.11.05-52] Service Worker lifecycle event: [waiting]
[Application 0.0.1.2019.11.05-52] handle waiting...
[Service Worker 2019-11-05 @ 16:07:32] Message event: [SKIP_WAITING]
[Application 0.0.1.2019.11.05-52] Service Worker lifecycle event: [redundant]
[Application 0.0.1.2019.11.05-52] Service Worker lifecycle event: [activating]
[Application 0.0.1.2019.11.05-52] Service Worker lifecycle event: [controlling]
[Service Worker 2019-11-05 @ 16:07:32] Lifecycle event: [activate]
[Application 0.0.1.2019.11.05-52] Service Worker lifecycle event: [activated]
[Application 0.0.1.2019.11.05-52] Reloading this window...
[Application 0.0.1.2019.11.05-53] <<<<<<<<<<<<<<< STARTING >>>>>>>>>>>>>>>
[Application 0.0.1.2019.11.05-53] Preloading 125 images...
[Application 0.0.1.2019.11.05-53] ServiceWorker registered!
А иногда просто зависает...
А иногда все просто застревает, когда доступна новая версия сервис-воркера. Вwaiting
или externalwaiting
обработчик событий никогда не запускается.
Когда это происходит, в консоли нет ошибок и нет ничего плохого в новой версии сервис-воркера.
Единственный способ избавиться от привязки - остановить активного сервис-воркера, отменить его регистрацию и перезагрузить.
Почему все это имеет значение?
Мне нужно убедиться, что процесс обновления работает безупречно на всех платформах, прежде чем я осмелюсь выпустить это приложение...
Если пользователь столкнется с какой-либо из этих проблем при выпуске обновления, ему будет сложно получить его, и я ничего не могу с этим поделать. Умножить на количество установок == огромная головная боль.
Все это сводится к трем вопросам: В порядке важности:
- Как я могу справиться
externalwaiting
чтоб новая версия сервис воркера загрузилась и активировалась? Как мне убедиться, чтоSKIP_WAITING
сообщение получено ожидающим работником службы? - Почему события жизненного цикла различаются между простой и внешней разновидностями?
- В целях тестирования я каждый раз делаю одно и то же обновление для сервис-воркера (новая версия предварительно кэшированного файла).
- У меня приложение загружается только на одной вкладке.
- Переход от простых событий к внешним кажется случайным.
- Почему процесс иногда застревает перед фазой ожидания жизненного цикла и что я могу с этим поделать?
1 ответ
Обратите внимание, что теперь эта проблема решена в окне Workbox. Есть обновленный расширенный рецепт:
https://developers.google.com/web/tools/workbox/guides/advanced-recipes
Также обратите внимание, что с кодом в этом рецепте есть (или были) проблемы. См. Исправленный код в следующей проблеме.