Только что была выпущена следующая основная версия очень популярной вспомогательной библиотеки PWA. Workbox 4 приносит много интересных дополнений к существующим модулям и только несколько незначительных критических изменений. Кроме того, он содержит один совершенно новый модуль под названием workbox-window, чтобы удовлетворить потребности разработчиков простым и мощным способом регистрации сервис-воркера, подключения к его жизненному циклу и предоставления двунаправленный канал связи с приложением. Это первый модуль Workbox, который будет использоваться в контексте окна, то есть в коде нашего приложения (не сервис-воркера).

Давайте исследуем этот новый модуль, чтобы проверить, что потребуется для создания хорошо известной техники «обновления до обновления версии» - одного из лучших методов пользовательского интерфейса для PWA. Поскольку мы часто используем этот поток при создании наших приложений, а Workbox теперь предоставляет соответствующие инструменты, нам просто нужно найти простой и надежный код для создания этого потока. Эта статья - моя попытка найти этот код: минимальный и стабильный. Но сначала, о чем я говорю?

Обновить до обновления версии 101

Вы открываете какой-то сайт. И через пару секунд он показывает вам подсказку / диалог, в котором говорится: «Доступна новая версия этого веб-сайта. [Обновите страницу, чтобы получить ее] ». В большинстве случаев это означает:

  1. Это источник, управляемый работником службы (если он также имеет манифест веб-приложения, мы можем назвать его PWA), и пользовательский интерфейс, который вы видите, не был получен из сети, а был взят из кеш-хранилища вашего браузера.
  2. Вы посещали этот сайт с помощью этого браузера некоторое время назад
  3. Между предыдущим и текущим посещениями развернутая версия была обновлена

Диалог, который вы видите, представляет собой своего рода компромисс между возможностью немедленно отобразить пользовательский интерфейс приложения, не извлекая его из сети (с использованием предварительно кэшированной версии), и необходимостью в конце концов доставить фактическую версию приложения пользователю. Где же тогда компромисс? Дело в том, что мы по-прежнему загружаем предварительно кэшированную («старую») версию приложения из кеш-хранилища, но если сервисный работник знает, что доступна новая версия, он извлекает обновленные ресурсы, обновляет кеш и отправляет сообщение ( используя Broadcast Channel API или postMessage) в приложение. Где мы ловим это сообщение и показываем пресловутую «Приложение обновлено. Нажмите «Обновить, чтобы загрузить» сообщение пользователю. Следующая загрузка страницы - и мы обслуживаем «новую» версию из Cache Storage (конечно, если наш сервис-воркер правильно выполнил все перечисленные выше операции).

Еще один вариант этого метода - мы не отправляем никакого сигнала от сервис-воркера, а слушаем изменения его жизненного цикла в нашем приложении. В нашем случае комбинация событий onupdatefound и onstatechange, вызванная выборкой разного байта сервис-воркера, может означать изменение хеш-сумм ресурсов, упомянутых в списке «для предварительного кэширования», введенных в сервис-воркер. Что, в свою очередь, означает, что была создана новая версия приложения, поэтому мы можем смело показывать сообщение «Приложение обновлено».

Параметры Workbox v3 для потока от обновления до обновления версии

Во-первых, позвольте сказать спасибо сопровождающим Workbox за волшебный метод precacheAndRoute(), который мы могли бы использовать в нашем собственном сервис-воркере. Этот метод берет на себя всю сложность предварительного кэширования, поддержки версий, извлечения обновленных ресурсов, обновления кеша и т. Д. Мы просто передаем объект с ресурсами и их хэш-суммами (созданными другим помощником из семейства Workbox - модулем workbox-build), и он работает. Кроме того, еще одна строка кода в сервис-воркере:

… И мы можем получать сигналы о том, что предварительно кэшированные ресурсы были обновлены в коде нашего приложения - именно то, что нам нужно, чтобы показать сообщение нашему пользователю:

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

Почему я рассказываю о параметрах, которые мы используем в Workbox 3, в статье о Workbox 4? Потому что он по-прежнему работает нормально - ваш код из v3, связанный с этим потоком, не сломается.

А как насчет второго варианта - когда мы полагаемся на события жизненного цикла сервис-воркера? В версии 3 у нас нет помощников для регистрации нашего сервис-воркера, управляемого Workbox, в коде приложения и подписки на его события. Конечно, мы всегда можем написать это сами или использовать действительно красивую библиотеку register-service-worker от Evan You, тогда код в нашем приложении может выглядеть так:

Но теперь у нас есть более мощный, гибкий и действительно нативный для Workbox способ добиться этого: модуль окна-рабочего окна. Как указано в документации, основными функциями / целями этого модуля являются:

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

Чтобы помочь разработчикам не допускать наиболее распространенных ошибок.

Чтобы упростить взаимодействие между кодом, запущенным в сервис-воркере, и кодом, запущенным в окне.

Давайте реализуем описанный выше трюк с UX с помощью этого модуля.

Поток обновления-обновления-версии на основе workbox-build

Начнем с самого начала. Чтобы продемонстрировать поток, нам нужно реализовать сервис-воркер с предварительным кэшированием и обслуживанием ресурсов, образующих оболочку нашего приложения.

Минималистичная версия исходного файла сервис-воркера на базе Workbox может выглядеть так:

Строки 8 и 9 важны в контексте этой статьи. Вы прочтете позже, зачем они нам

Почему этот исходный файл? Потому что мы должны обрабатывать его после каждой сборки нашего приложения. Чтобы быть точным - мы должны ввести список ресурсов для предварительного кеширования и их хеш-суммы в качестве параметра для метода precacheAndRoute() (вместо этого пустого массива). Чтобы избавить нас от этой скучной задачи, у Workbox есть 3 варианта на выбор: Workbox CLI, плагин Webpack и модуль Node. Последний вариант - мой выбор: ему не нужен ни глобально установленный интерфейс командной строки, ни файл конфигурации Webpack. Установка модуля workbox-build:

npm install workbox-build --save-dev

Теперь скрипт сборки сервис-воркера:

И последняя часть - добавить скрипт npm run, объединяющий сборку нашего приложения и сервис-воркера, один за другим:

Как вы могли заметить, в моем примере я использую приложение Angular (ng build --prod - это команда сборки для него), но все, что я описываю в этой статье о модулях Workbox и методах PWA, применимо к любому приложению JavaScript.

После того, как я сделаю npm run build-pwa, я вижу что-то вроде

Generated dist/angular-pwa/service-worker.js, which will precache 6 files, totaling 735289 bytes.

Сервисный воркер в папке распространения теперь содержит всю информацию, которую Workbox должен знать о нашем приложении:

То же самое будет и в Workbox 3. Но теперь начинается различие: давайте зарегистрируем этого сервис-воркера в нашем приложении с помощью workbox-window. Сначала устанавливаем модуль:

npm install workbox-window

Подсказка: доступны разные сценарии импорта / использования / комплектации этого модуля.

Теперь в коде нашего приложения:

Обратите внимание на несколько важных моментов:

  1. В register() методе нет функции Service worker, поэтому не забудьте включить это в свой код (строка 3). В то же время отложена регистрация до события window.onload, поэтому нам не нужно добавлять эту дополнительную оболочку.
  2. Где именно разместить этот код в вашем приложении? Чем позже - тем лучше. Сделайте это после того, как ваше приложение будет полностью отрисовано, чтобы сервис-воркер не конкурировал с основным потоком за ресурсы сети и ЦП. Для приложений Angular лучшее место будет в then() блоке после bootstrapModule() вызова в main.ts файле.

Пришло время запустить наше приложение на любом статическом http-сервере. Я использую serve:

Это именно то, что мы и ожидали: сервис-воркер был зарегистрирован, некоторые файлы были предварительно кэшированы. Теперь, если вы выключите сервер или установите флажок Offline в DevTools - приложение по-прежнему будет доступно. Благодаря нашему сервисному работнику на базе Workbox, обслуживающему ресурсы из кеш-хранилища.

Подсказка: чтобы иметь более подробный журнал, просто установите соответствующий уровень ведения журнала в DevTools - см. Раскрывающееся меню Уровни по умолчанию в правом нижнем углу снимка экрана.

Пришло время обновить что-нибудь в нашем приложении. Давайте изменим заголовок на Angular PWA 6. Создайте / разверните / обслужите / обновите страницу: вы все равно увидите Angular PWA 5. Еще раз нажмите кнопку обновления браузера - теперь вы видите новый заголовок. Это было ожидаемо, и наша цель - дать пользователю подсказку о том, что приложение было действительно обновлено, пока он видит старую версию. Один из слушателей, выставленных рабочим окном-окном, под названием installed поможет!

Теперь при каждом обновлении приложения мы будем видеть подсказку:

Некоторые примечания:

  1. В коде есть дополнительное условие - event.isUpdate. Это связано с тем, что мы не хотим отображать это сообщение при самой первой установке Service worker, а только при обновлении. Инверсия этого условия - хороший вариант для отображения сообщения типа «Это приложение теперь готово для использования в автономном режиме».
  2. Описанный подход работает ТОЛЬКО в том случае, если мы умеем изменять жизненный цикл сервис-воркера, пропуская фазу ожидания (см. Строки 8 и 9 в нашем коде сервис-воркера). Без этой модификации новый сервис-воркер не будет активирован, пока пользователь не закроет все открытые вкладки с этим приложением - в результате они будут видеть старую версию до этого. Если по какой-то причине пропуск шага активации не подходит для вашего проекта - используйте более общий (и более сложный) вариант, упомянутый в документации.
  3. Пожалуйста, не используйте confirm() метод JavaScript в продакшене :) Он включен в пример кода только для простоты. Используйте менее навязчивые и неблокирующие тосты / закуски из библиотеки пользовательского интерфейса, которую вы используете для своего приложения.

Потрясающие! Теперь у нас есть довольно лаконичный код, который помогает нам зарегистрировать сервис-воркера и уловить подходящий момент, когда доступно отображение сообщения о выходе новой версии.

Конечно, в workbox-window есть много других полезных событий, помогающих нам иметь полный контроль над сервисными воркерами: как внутренними (зарегистрированными с помощью workbox-window), так и внешними - все остальные, например, от сторонних разработчиков. сервисы, предоставляющие Push-уведомления. Также это дает удобную возможность общаться с сервис-воркером, которая будет расширена и стандартизирована с выходом модуля workbox-messages.

Подводить итоги:

  1. Выпущен Workbox 4 - готовая к производству библиотека для автоматизации основных сетевых задач PWA.
  2. В новом модуле рабочее окно-окно дает разработчикам удобный способ зарегистрировать сервис-воркера и прослушивать события его жизненного цикла.
  3. Мы обнаружили правильное событие, на которое нужно реагировать для отображения сообщения пользователю в потоке обновления до обновления версии.

Итак, давайте попробуем новый Workbox 4 и его оконный модуль! Если вы обнаружите какие-либо проблемы, сообщите. Если вы хотите быть в курсе всех последних новостей о Workbox и PWA в целом, подписывайтесь на меня в Twitter webmaxru и присоединяйтесь к команде PWA Slack. Мои личные сообщения всегда открыты для ваших технических вопросов и приглашений рассказать о PWA / Workbox на вашей конференции или провести семинар по PWA для вашей конференции / компании.