Несогласованное поведение с 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событие запускается, этот процесс работает нормально.

  1. Внесите небольшое обновление в приложение, которое приведет к изменению файла сервис-воркера.
  2. Нажмите кнопку "Проверить наличие обновлений".
  3. Найден новый сервисный работник, и пользователю предлагается установить обновление
  4. Страница перезагружена.

Но если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]

В сети

  1. Пользователь только что нажал кнопку "Проверить наличие обновлений".
  2. На сайте обнаружена новая версия сервис-воркера.2019-11-05 @ 15:23:14и разбирается. Мы назовем это SWv2.
  3. Workbox загружен SWv2.
  4. SWv2installобработчик событий выполняется.
  5. Окно Workboxexternalinstalledобработчик событий выполняется.
  6. Окно Workboxexternalwaitingобработчик событий выполняется.
  7. Окно рабочего окна externalwaiting обработчик событий отправляет SKIP_WAITINGсообщение с использованиемworkboxWindow.messageSW()
  8. 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обработчик событий никогда не запускается.

Когда это происходит, в консоли нет ошибок и нет ничего плохого в новой версии сервис-воркера.

Единственный способ избавиться от привязки - остановить активного сервис-воркера, отменить его регистрацию и перезагрузить.

Почему все это имеет значение?

Мне нужно убедиться, что процесс обновления работает безупречно на всех платформах, прежде чем я осмелюсь выпустить это приложение...

Если пользователь столкнется с какой-либо из этих проблем при выпуске обновления, ему будет сложно получить его, и я ничего не могу с этим поделать. Умножить на количество установок == огромная головная боль.

Все это сводится к трем вопросам: В порядке важности:

  1. Как я могу справиться externalwaitingчтоб новая версия сервис воркера загрузилась и активировалась? Как мне убедиться, чтоSKIP_WAITING сообщение получено ожидающим работником службы?
  2. Почему события жизненного цикла различаются между простой и внешней разновидностями?
    • В целях тестирования я каждый раз делаю одно и то же обновление для сервис-воркера (новая версия предварительно кэшированного файла).
    • У меня приложение загружается только на одной вкладке.
    • Переход от простых событий к внешним кажется случайным.
  3. Почему процесс иногда застревает перед фазой ожидания жизненного цикла и что я могу с этим поделать?

1 ответ

Обратите внимание, что теперь эта проблема решена в окне Workbox. Есть обновленный расширенный рецепт:

https://developers.google.com/web/tools/workbox/guides/advanced-recipes

Также обратите внимание, что с кодом в этом рецепте есть (или были) проблемы. См. Исправленный код в следующей проблеме.

https://github.com/GoogleChrome/workbox/issues/2430

Другие вопросы по тегам