Перейти к содержанию

Уведомление пользователей об обновлениях

изображение названия и автора

Добро пожаловать в день неделя 2 день 7 из серии 30 Days of PWA! В сегодняшней статье мы расскажем о различных способах уведомления и повторного привлечения пользователей к работе с вашим приложением.

Что такое уведомления?

Уведомление в контексте веб-приложения — это способ повторного привлечения пользователей. Часто они используются для предупреждения пользователей о том, что происходит в бэкенде приложения и/или в самом приложении. Например:

  • Новое сообщение в чате
  • Доступна новая версия приложения
  • Ваш рейс готов к регистрации.

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

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

В этой главе мы рассмотрим некоторые интересные возможности информирования пользователей, используя возможности Progressive Web App APIs.

Значки приложений

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

Аналогичный механизм можно использовать и для веб-приложений, используя Badging API. Разумеется, поскольку речь идет о значке приложения, мы имеем в виду именно установленные веб-приложения (т.е. с поддержкой работы в автономном режиме через сервис-воркер и корректным манифестом веб-приложения) — подробнее об этом читайте в разделах "Make PWA Installable" и "Make PWA Work Offline".

Реализация значков

Для управления значком над иконкой приложения можно воспользоваться двумя методами: setAppBadge() и clearAppBadge(). Предположим, что мы хотим проинформировать пользователя о двух новых сообщениях в почтовом ящике:

1
2
3
4
5
6
// Check if the API is supported
if ('setAppBadge' in navigator) {
    navigator.setAppBadge(2).catch((error) => {
        // Code to handle an error
    });
}

Для удаления значка:

1
navigator.clearAppBadge();

или

1
navigator.setAppBadge(0);

Так выглядит значок приложения со значком на панели задач Windows 11:

Значок приложения на панели задач Windows

Здесь значок с синим накладным значком — это PWA.

Управлять значком можно как из основного приложения, так и из сервиса-воркера. В последнем случае очень важно установить значок, когда вкладка приложения (или даже видимая часть браузера) не открыта. Какие наиболее значимые события необходимо прослушивать в сервисе-воркере для управления бейджами? На данный момент их два со своими плюсами и минусами:

push

когда получено push-уведомление. Плюсы: мы контролируем точное время отправки запроса на уведомление. Минусы: все требования и ограничения Push API (подробнее см. ниже). Кроме того, при получении push-уведомления обязательно должно отображаться уведомление браузера, поэтому мы не можем выпустить "тихое" обновление бейджа.

periodicsync

событие из Periodic Background Sync API, о котором мы рассказывали в разделе "Синхронизация приложения в фоновом режиме". Плюсы: не требуется никаких других действий или уведомлений, обновление бейджа может происходить в фоновом режиме. Минусы: все требования и ограничения API периодической фоновой синхронизации. Одно из них заключается в том, что нет возможности обновлять значок в определенное время — браузер сам решает, когда вызвать это событие для конкретного установленного приложения, основываясь на индексе Site Engagement. И перерыв между синхронизациями составит в лучшем случае несколько часов.

Как видите, на данный момент не существует идеального способа управления значком из сервис-воркера. Дискуссия на эту тему продолжается, и есть несколько предложений о том, как улучшить работу Push API с бейджами.

Push-уведомления в Интернете

Еще одна известная функция мобильных платформ, пришедшая в веб и имеющая отношение к задаче информирования пользователей, — это push-уведомления. Они представляют собой способ отправки пакета данных (который может состоять из заголовка, краткого описания, url, изображения, нескольких других видов данных) на устройство пользователя с вашего бэкенда. Часто push-уведомления объясняются как возможность для владельцев приложений повторно привлечь пользователей. Отличительными особенностями push-уведомлений являются:

  • Для отображения уведомления всегда используются элементы управления пользовательским интерфейсом, специфичные для ОС или браузера. Для веб это Notifications API. Обеспечивается наилучшее взаимодействие разработчика и пользователя.
  • Пользователи явно соглашаются на получение push-уведомлений и могут отказаться от них в любой момент. Если разработчик приложения не предоставляет такой возможности в пользовательском интерфейсе, пользователи могут использовать специфические для платформы инструменты для блокировки push-уведомлений для приложения (на мобильных платформах) или для источника (в Интернете).
  • При этом пользовательское устройство может получать и показывать эти уведомления независимо от того, открыто приложение или нет. Таким образом, для веб-платформы мы слушаем и реагируем на соответствующее событие в сервисе-воркере.
  • Всегда есть сторонний сервис, который обрабатывает подписки и отправляет push-уведомления на пользовательские устройства. Он называется "Messaging Service" и не является частью ни операционной системы, ни браузера. Messaging Service — это мощный сервер и сетевая инфраструктура, способная доставлять сообщения непосредственно на устройства в огромных масштабах. Как разработчик, вы не можете (и не должны) выбирать конкретный Messaging Service — вы неявно используете его в своем коде, который работает с Push API при подписке, отписке, отправке уведомления. И это бесплатно.

Реализация push-уведомлений

Реализация push-уведомлений в Интернете включает в себя несколько шагов:

Шаг 1. Получение учетных данных

Сгенерируйте набор "ключей VAPID" для аутентификации пользовательского устройства в службе сообщений. Для каждого приложения необходим один набор ключей (открытый и закрытый). Для этого можно использовать модуль web-push или один из многочисленных бесплатных онлайн-сервисов. Использование web-push:

1
2
npm install web-push -g
web-push generate-vapid-keys --json

Шаг 2. Подписка и сохранение

После того как пользователь явно согласится получать push-уведомления (например, нажав кнопку в пользовательском интерфейсе), используйте метод subscribe() интерфейса PushManager (если он доступен) активной регистрации сервис-воркера:

При отсутствии поддержки Push API в браузере лучше всего скрыть или отключить все связанные с ним элементы управления пользовательским интерфейсом:

1
2
3
4
5
6
if (!('PushManager' in window)) {
    // Code to disable or hide push-related UI controls

    console.log('Push API is not supported');
    return;
}

Обработчик кнопки "Подписаться" (в целях примера код упрощен и не содержит обработки ошибок):

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
async function subscribeForPush() {
    const registration =
        await navigator.serviceWorker.ready;

    const pushSubscription =
        await registration.pushManager.subscribe({
            userVisibleOnly: true, // Should be always true as currently browsers only support explicitly visible notifications
            applicationServerKey:
                'publicKey from Step 1 converted to Uint8Array',
        });

    // Send push subscription to our server to persist it
    saveSubscription(pushSubscription);
}

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

  • Вы можете запросить статус подписки у службы сообщений, используя getSubscription() для установки начального статуса для элементов управления пользовательского интерфейса подписки.
  • Перед подпиской целесообразно проверить/запросить разрешение на получение уведомления с помощью Notifications API. Это даст вам больше возможностей контролировать время отображения запроса на разрешение. Если пропустить этот шаг, то при вызове subscribe() пользователю будет предложено предоставить/запретить разрешение на получение уведомления.
  • Не забудьте реализовать логику отмены подписки и разместить соответствующие элементы управления пользовательским интерфейсом. Всегда лучше позволить пользователю отписаться от рассылки с помощью вашего кода (он сможет повторно подписаться на рассылку в вашем приложении), чем заставлять его блокировать ваш источник с помощью настроек браузера (что приведет к необходимости повторно разблокировать ваш источник в настройках браузера, если он захочет повторно подписаться на рассылку).

Расширенный пример кода, включающий также метод преобразования publicKey в Uint8Array, можно найти здесь.

Шаг 3. Отправка уведомления

В своем бэкенде пройдитесь по объектам push-подписки, которые вы получили и сохранили на шаге 2, чтобы отправить для каждого из них специальный HTTPS-запрос в службу сообщений. Следует помнить, что push-уведомления в Интернете не ограничиваются широковещательными сообщениями. Вы можете отправить конкретное уведомление на конкретное пользовательское устройство, если вместе с объектом push-подписки передадите бэкенду некоторые идентифицирующие пользователя данные (например, внутренний идентификатор пользователя), чтобы можно было итерироваться только по конкретным подпискам.

Для построения запроса, соответствующего протоколу Web Push, используется:

  • поле endpoint из объекта подписки, которое на самом деле является URL службы сообщений с уникальным токеном устройства
  • ключи VAPID, сгенерированные на шаге 1
  • полезную нагрузку, которую вы хотите отправить на устройство пользователя для данного конкретного уведомления. Часто для этого используется JSON.stringify() объект, соответствующий спецификации Notification.

Более простым способом отправки уведомления из бэкенда NodeJS является использование метода sendNotification() из модуля web-push. Существуют аналогичные библиотеки для других платформ.

Служба сообщений получает запрос и отправляет пользователю push-уведомление.

Шаг 4. Получение и отображение

Для получения уведомления сервис-воркер на пользовательском устройстве прослушивает событие push и обрабатывает его:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
self.addEventListener('push', (event) => {
    const notificationData = JSON.parse(event.data.text());

    event.waitUntil(
        self.registration.showNotification(notificationData.title, {
            body: notificationData.message,
            icon: notificationData.icon
        });
    );
});

Для реакции на действия пользователя в сервисе-воркере также можно предусмотреть обработчики событий notificationclick и notificationclose.

В связи с веб-спецификой push-уведомления имеют ряд дополнительных интересных моментов:

  • Показ уведомления с данными, отправленными в качестве полезной нагрузки с вашего сервера (проксируемого службой сообщений), является лишь одним из возможных сценариев. Перед показом уведомления можно, например, выполнить еще один вызов API для запроса дополнительных данных. Конечно, при этом необходимо учитывать ограниченное время выполнения сервис-воркера. Поэтому все, что происходит в коде до вызова showNotification(), не должно быть слишком длинным.
  • В сервисе-воркере при получении события push вы ДОЛЖНЫ использовать метод showNotification() для показа пользователю уведомления, специфичного для данной платформы. Если этот метод не будет вызван или будет вызван некорректно, то все равно будет показано уведомление, информирующее пользователя о том, что "что-то произошло с вашим приложением в фоновом режиме" (точный текст определяется браузером). Это сделано для того, чтобы вредоносные приложения не могли "разбудить" сервис-воркеры по сигналу из бэкенда, не сообщая об этом пользователю.
  • В Windows push-уведомления интегрированы в Центр действий.

Push-уведомление в Центре действий Windows

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

Существует демо с доступным исходным кодом, который можно использовать для изучения функциональности уведомлений.

Подробнее об уведомлении пользователей об обновлениях

Комментарии