Непоследовательное поведение с workbox-window.update () - PullRequest
2 голосов
/ 02 ноября 2019

Платформа

"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

Я используюметод workbox-window 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.

Stuck waiting

Пропустить ожидающее сообщение, полученное старымработник службы

Если пользователь подтверждает, что он хочет обновить сообщение SKIP_WAITING, полученное более старым, активированным определением работника службы.

Вот выдержка из моих журналов, подтверждающая это.

  • Записи журнала со стороны приложения / клиента начинаются с префикса «Приложение», за которым следует версия приложения.
  • В записи журнала от работника службы добавляется префикс «Service Worker», за которым следует метка даты DOB, уникальная для каждого экземпляра работника службы.
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]

On line

  1. Пользователь только что нажал кнопку «проверить наличие обновлений».
  2. В 2019-11-05 @ 15:23:14 была обнаружена новая версия работника сервиса, и она анализируется. Мы назовем это SWv2.
  3. Workbox загружен SWv2.
  4. SWv2 install обработчик событий выполнен.
  5. Окно Workbox externalinstalled обработчик событий выполнен.
  6. Выполнен обработчик события окна рабочего окна externalwaiting.
  7. Обработчик события окна рабочего окна externalwaiting отправляет сообщение SKIP_WAITING с использованием workboxWindow.messageSW()
  8. Service Workerv1 (загруженный на 2019-11-05 @ 15:20:03) получает сообщение об ожидании пропуска. Ничего не произошло. SWv2 остается в состоянии ожидания.

Контрастность с обычным событием ожидания

В следующем журнале видно, что сообщение SKIP_WAITING полученоожидающий работник службы: v 2019-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 никогда не запускается.

Chrome Dev Tools

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

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

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

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

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

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

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