Codelab: создание клиента push-уведомлений

Кейт Джеффрис
Kate Jeffreys
Кейс Баскс
Kayce Basques

В этом практическом занятии вы шаг за шагом узнаете, как создать клиент push-уведомлений. К концу практического занятия у вас будет клиент, который:

  • Подписывает пользователя на push-уведомления.
  • Получает push-сообщения и отображает их в виде уведомлений.
  • Отписывает пользователя от push-уведомлений.

Эта практическая работа направлена на обучение на практике и не слишком подробно рассматривает концепции. Подробнее о концепциях push-уведомлений читайте в статье «Как работают push-уведомления?» .

Серверный код этой лабораторной работы уже готов. В ней вам останется только реализовать клиентскую часть. Чтобы узнать, как реализовать сервер push-уведомлений, ознакомьтесь с практической работой: Создание сервера push-уведомлений .

Совместимость с браузерами

Известно, что эта лабораторная работа работает со следующими комбинациями операционных систем и браузеров:

  • Windows: Chrome, Edge
  • macOS: Chrome, Firefox
  • Android: Chrome, Firefox

Известно, что эта лабораторная работа не работает со следующими операционными системами (или комбинациями операционной системы и браузера):

  • macOS: Brave, Edge, Safari
  • iOS

Настраивать

Получите редактируемую копию кода

  • Нажмите «Ремикс для редактирования», чтобы сделать проект редактируемым.

Настроить аутентификацию

Прежде чем запускать push-уведомления, необходимо настроить сервер и клиент с ключами аутентификации. Подробнее об этом см. в статье «Подпись запросов протокола web push» . Обычно секретные данные хранятся в файле .env , похожем на этот.

VAPID_PUBLIC_KEY="BKiwTvD9HA…"
VAPID_PRIVATE_KEY="4mXG9jBUaU…"
VAPID_SUBJECT="mailto:test@test.test"
  • Откройте public/index.js .
  • Замените VAPID_PUBLIC_KEY_VALUE_HERE на значение вашего открытого ключа.

Регистрация работника сферы услуг

В конечном итоге вашему клиенту понадобится сервис-воркер для получения и отображения уведомлений. Рекомендуется зарегистрировать сервис-воркер как можно раньше. Подробнее см. в разделе Получение и отображение push-сообщений в виде уведомлений .

  • Замените комментарий // TODO add startup logic here следующим кодом:
// TODO add startup logic here
if ('serviceWorker' in navigator && 'PushManager' in window) {
  navigator.serviceWorker.register('./service-worker.js').then(serviceWorkerRegistration => {
    console.info('Service worker was registered.');
    console.info({serviceWorkerRegistration});
  }).catch(error => {
    console.error('An error occurred while registering the service worker.');
    console.error(error);
  });
  subscribeButton.disabled = false;
} else {
  console.error('Browser does not support service workers or push messages.');
}

subscribeButton.addEventListener('click', subscribeButtonHandler);
unsubscribeButton.addEventListener('click', unsubscribeButtonHandler);
  • Нажмите `Control+Shift+J` (или `Command+Option+J` на Mac), чтобы открыть DevTools.
  • Перейдите на вкладку «Консоль» . Вы увидите сообщение Service worker was registered. Вход в консоль выполнен.

Запросить разрешение на push-уведомления

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

  • В public/index.js замените комментарий // TODO в subscribeButtonHandler() следующим кодом:
// TODO
// Prevent the user from clicking the subscribe button multiple times.
subscribeButton.disabled = true;
const result = await Notification.requestPermission();
if (result === 'denied') {
  console.error('The user explicitly denied the permission request.');
  return;
}
if (result === 'granted') {
  console.info('The user accepted the permission request.');
}
  • Вернитесь на вкладку приложения и нажмите «Подписаться на push- уведомления». Ваш браузер или операционная система, вероятно, спросят вас, хотите ли вы разрешить сайту отправлять вам push-уведомления. Нажмите «Разрешить» (или любую другую фразу, используемую в вашем браузере/ОС). В консоли вы увидите сообщение о том, был ли запрос принят или отклонён.

Подписаться на push-уведомления

Процесс подписки включает взаимодействие с веб-сервисом, управляемым поставщиком браузера, который называется push-сервисом . Получив информацию о подписке на push-уведомления, необходимо отправить её на сервер и обеспечить её долгосрочное хранение в базе данных. Подробнее о процессе подписки см. в статье «Подписка клиента на push-уведомления» .

  • Добавьте следующий выделенный код в subscribeButtonHandler() :
subscribeButton.disabled = true;
const result = await Notification.requestPermission();
if (result === 'denied') {
  console.error('The user explicitly denied the permission request.');
  return;
}
if (result === 'granted') {
  console.info('The user accepted the permission request.');
}
const registration = await navigator.serviceWorker.getRegistration();
const subscribed = await registration.pushManager.getSubscription();
if (subscribed) {
  console.info('User is already subscribed.');
  notifyMeButton.disabled = false;
  unsubscribeButton.disabled = false;
  return;
}
const subscription = await registration.pushManager.subscribe({
  userVisibleOnly: true,
  applicationServerKey: urlB64ToUint8Array(VAPID_PUBLIC_KEY)
});
notifyMeButton.disabled = false;
fetch('/add-subscription', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json'
  },
  body: JSON.stringify(subscription)
});

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

Значение applicationServerKey основано на служебной функции, которая преобразует строку base64 в массив Uint8Array. Это значение используется для аутентификации между вашим сервером и службой push-уведомлений.

Отписаться от push-уведомлений

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

  • Замените комментарий // TODO в unsubscribeButtonHandler() следующим кодом:
// TODO
const registration = await navigator.serviceWorker.getRegistration();
const subscription = await registration.pushManager.getSubscription();
fetch('/remove-subscription', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({endpoint: subscription.endpoint})
});
const unsubscribed = await subscription.unsubscribe();
if (unsubscribed) {
  console.info('Successfully unsubscribed from push notifications.');
  unsubscribeButton.disabled = true;
  subscribeButton.disabled = false;
  notifyMeButton.disabled = true;
}

Получайте push-сообщение и отображайте его как уведомление

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

  • Откройте public/service-worker.js и замените комментарий // TODO в обработчике событий push сервис-воркера следующим кодом:
// TODO
let data = event.data.json();
const image = 'logo.png';
const options = {
  body: data.options.body,
  icon: image
}
self.registration.showNotification(
  data.title, 
  options
);
  • Вернитесь на вкладку приложения.
  • Нажмите «Уведомить меня» . Вы получите push-уведомление.
  • Попробуйте открыть URL-адрес вкладки вашего приложения в других браузерах (или даже на других устройствах), пройти процедуру оформления подписки и нажать «Уведомить всех» . Вы должны получить одинаковое push-уведомление во всех браузерах, на которые вы подписаны. См. раздел «Совместимость браузеров» , чтобы ознакомиться со списком совместимых и несовместимых сочетаний браузера и ОС.

Вы можете настроить уведомление различными способами. Подробнее см. в параметрах ServiceWorkerRegistration.showNotification() .

Открывать URL-адрес, когда пользователь нажимает на уведомление

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

  • Замените комментарий // TODO в обработчике событий notificationclick сервисного работника следующим кодом:
// TODO
event.notification.close();
event.waitUntil(self.clients.openWindow('https://web.dev'));
  • Вернитесь на вкладку приложения, отправьте себе ещё одно уведомление и нажмите на него. Браузер должен открыть новую вкладку и загрузить https://web.dev .

Следующие шаги