Создание системы веб-уведомлений для новостей от Guardian Mobile Innovation Lab.

Настройка сервисного работника

Для реализации web push-уведомлений требуется service worker. Сервисные работники можно рассматривать как независимые процессы Javascript, которые выполняются в отдельном потоке и имеют ограниченный доступ к API браузера (сервисные работники не имеют доступа к DOM, API геолокации и т. д.).

Важное примечание. Во время нашей реализации push-уведомления были (и остаются) движущейся целью для Firefox. Мы провели проверки на нашей странице регистрации, чтобы убедиться, что пользователи, желающие участвовать, используют браузер, поддерживающий сервис-воркеры и веб-пуш.

Это код нашего сервисного работника. Его можно разделить на два раздела:

Аналитика

Google Analytics поддерживает компонент отслеживания и аналитики нашего сервисного работника.

Нам пришлось обойти несколько нюансов сервис-воркеров при внедрении аналитики. Поскольку сервис-воркеры по своей сути асинхронны, они могут использовать только API с асинхронными функциями. Это означает отсутствие доступа к синхронному XHR API (откат к асинхронному Fetch API). Еще одно важное предостережение: сервисные работники не могут получить доступ к Cookie API (среди других API браузера, таких как DOM и геолокация).

Стандартный код отслеживания Google Analytics зависит от функций браузера, таких как Cookies API и синхронный XHR. К счастью, у Google Analytics есть внешний API (Протокол измерения Google Analytics). В API есть краткое руководство по внедрению собственного кода отслеживания, которое можно использовать в сервис-воркере (но не стесняйтесь использовать наше).

Мы можем разбить код нашего основного сервис-воркера на три части:

Установка сервисного работника

Установка сервис-воркера инкапсулируется в следующие шаги:

  1. Проверить, чтобы устройство и браузер пользователя поддерживали сервис-воркеры
  2. Попытка установить сервис-воркер на устройство пользователя
  3. Даже если в браузере пользователя реализован API сервис-воркера, он может не полностью поддерживать сервис-воркеры и веб-push-уведомления. Выполните несколько ручных проверок, чтобы убедиться, что пользователь использует браузер и устройство, которые мы хотим поддерживать.
  4. Сервис-воркер должен быть успешно установлен (и теперь мы можем подписать пользователя на тему push-уведомлений)

Общение сервисного работника и клиента

Примечание. В этом разделе «клиент» относится к основному потоку Javascript в браузере пользователя

Общение с сервис-воркером осуществляется посредством передачи сообщений.

Передача сообщений в сервис-воркерах использует Channel Messaging API, а интерфейс Message Channel реализован с обратными вызовами. Чтобы справиться с этим несоответствием, мы внедрили код, найденный в GoogleChrome Sample Github repo, чтобы обернуть код передачи сообщений в промис. Мы используем обещания для координации асинхронных аспектов нашего кода Javascript.

Функционал нашего сервис-воркера можно разделить на две части:

Отображение push-уведомлений из Интернета

Для получения push-уведомлений наш сервис-воркер подписывается на PushEvents. И Mozilla, и Google предоставляют примеры полей данных этих Push-событий, но не стесняйтесь обращаться к разделу PushMessageData в Спецификации W3C Notifications API.

Отображение уведомления

Сначала мы подписываем нашего сервис-воркера на push-событие. Любое push-уведомление, полученное нашим сервис-воркером, затем десериализуется в json.

Заставить нашего сервис-воркера показать уведомление — это просто вопрос того, чтобы ServiceWorkerRegistration вызывал метод showNotification с правильными параметрами.

Реакция на действия пользователя

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

Вот Суть одного примера нашего контракта полезной нагрузки уведомлений.

Сопоставления команд

Наш контракт структурирован таким образом, что имена команд сопоставляются с функциональностью сервис-воркера. В наших контрактных командах, таких как openURL, требуется параметр, который отражается в нашей полезной нагрузке.

Контракт также поддерживает Действия по уведомлению. Текст уведомления, значок и команда заключены в options, а кнопки действий (если они необязательны) содержатся в поле actionCommands.

Реагирование на события щелчка включает в себя привязку к событию notificationclick или notificationclose, а затем анализ объекта события.

Важно. Как отличить клик по уведомлению от клика по действию с уведомлением? Свойство action объекта события! В документации для showNotification параметр options имеет свойство, называемое actions, которое может быть заполнено массивом объектов. Значение свойства action этого объекта — это то, что будет передано объекту события при щелчке.

В нашем коде для запуска команд при щелчке уведомления мы определяем, заполнено ли свойство action события notificationclick.

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

Важно: на момент написания этой статьи только Chrome реализовал и отправил событие notificationclose. Событие было реализовано в Firefox, но еще не было отправлено на момент написания этой статьи (стабильная версия релиза FF на момент написания этой статьи: 47.0.1).

Обновление сервисного работника

Интерфейс ServiceWorkerRegistration предоставляет метод обновления сервисного работника. В нашем коде мы обновляем Service Workers пользователя, отправляя уведомление с командой обновления.

Примечание На момент написания этой статьи Google Chrome требует от Service Worker видимого отображения уведомления при получении push-сообщения (обоснование требования можно найти здесь). В нашем коде обновления мы не выполняем showNotification, поэтому пользователю будет показано уведомление Google Chrome по умолчанию.

Причуды сервисного работника

Chromium реализует собственные push-уведомления, используя Android Notification API с помощью JNI. Покрытие Notification API в Chromium обширно, и такие функции, как обновление уведомлений, доступны для Web Notification API. Несмотря на это, мы столкнулись с некоторыми особенностями при использовании веб-push-уведомлений.

Обновление уведомления

Мы заметили странность, когда хотели обновить уведомление на месте (пример: обновление уведомления на месте с результатами праймериз). Это достигается путем отправки push-уведомления с тем же параметром tag (упомянутым в документации showNotification на MDN). При отправке обновления, если на экране блокировки было несколько уведомлений, обновленное уведомление временно перемещалось в верхнюю часть экрана, а затем возвращалось в исходное положение без участия пользователя.

Открытие веб-страницы

Одним из требований к нашим уведомлениям было предоставление пользователю возможности щелкнуть уведомление, чтобы открыть веб-страницу. Это распространенный вариант использования, который задокументирован на MDN. Обратите внимание, что в документации параметр url Как правило… должен быть URL-адресом из того же источника, что и вызывающий скрипт.. Если пользователь уже щелкнул по открывшемуся уведомлению веб-страницу, а затем снова щелкнул это же уведомление, откроется вторая веб-страница (вместо того, чтобы просто сосредоточиться на уже открытой странице).

Лаборатория мобильных инноваций Guardian работает при щедрой поддержке Фонда Джона С. и Джеймса Л. Найтов.