Push уведомления

Push уведомления представляют собой механизм, позволяющий веб-приложению отправлять сообщения пользователю вне зависимости от того, активно ли окно браузера. В Preact их интеграция строится на стандартных веб-технологиях: Service Worker, Push API и Notifications API. Preact, как лёгкий и высокопроизводительный фреймворк, не предоставляет встроенных решений для push, но его компонентная архитектура упрощает организацию кода и управление состоянием подписки.


Регистрация Service Worker

Service Worker — отдельный скрипт, который работает в фоне и отвечает за обработку push-сообщений. В Preact его регистрация обычно выполняется при старте приложения:

if ('serviceWorker' in navigator && 'PushManager' in window) {
  navigator.serviceWorker.register('/service-worker.js')
    .then(registration => {
      console.log('Service Worker зарегистрирован:', registration);
    })
    .catch(error => {
      console.error('Ошибка регистрации Service Worker:', error);
    });
}

Ключевые моменты:

  • Скрипт service-worker.js должен находиться в корне сайта или в поддиректории с корректным scope.
  • Проверка поддержки браузером обязательна, так как не все старые версии поддерживают Push API.

Подписка на Push уведомления

Подписка выполняется через объект PushManager, который доступен у зарегистрированного Service Worker:

async function subscribeUser() {
  const registration = await navigator.serviceWorker.ready;
  const subscription = await registration.pushManager.subscribe({
    userVisibleOnly: true,
    applicationServerKey: urlBase64ToUint8Array('<VAPID_PUBLIC_KEY>')
  });
  console.log('Подписка на Push уведомления:', subscription);
  return subscription;
}

Объяснение ключевых параметров:

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

Функция urlBase64ToUint8Array используется для конвертации ключа из формата Base64 в Uint8Array.


Обработка уведомлений в Service Worker

Внутри Service Worker реализуется обработка событий push и notificationclick:

self.addEventListener('push', event => {
  const data = event.data.json();
  const options = {
    body: data.body,
    icon: '/icon.png',
    badge: '/badge.png'
  };
  event.waitUntil(
    self.registration.showNotification(data.title, options)
  );
});

self.addEventListener('notificationclick', event => {
  event.notification.close();
  event.waitUntil(
    clients.openWindow('https://example.com')
  );
});

Основные моменты:

  • event.data.json() позволяет извлечь полезную нагрузку сообщения.
  • showNotification отображает уведомление на устройстве пользователя.
  • Обработка клика через notificationclick позволяет реализовать навигацию по приложению.

Управление подписками и серверная интеграция

Подписка пользователя обычно отправляется на сервер для хранения и дальнейшей отправки push-сообщений. Серверная часть может использовать библиотеки, такие как web-push для Node.js:

import webPush from 'web-push';

webPush.setVapidDetails(
  'mailto:admin@example.com',
  process.env.VAPID_PUBLIC_KEY,
  process.env.VAPID_PRIVATE_KEY
);

const pushSubscription = { /* объект подписки из браузера */ };
const payload = JSON.stringify({ title: 'Привет!', body: 'Новое уведомление' });

webPush.sendNotification(pushSubscription, payload)
  .then(() => console.log('Push отправлен'))
  .catch(err => console.error('Ошибка при отправке push:', err));

Важно учитывать:

  • Подписка может устаревать или быть удалена пользователем. Сервер должен корректно обрабатывать ошибки отправки.
  • Payload должен быть минимальным для снижения нагрузки и ускорения доставки.

Интеграция с компонентами Preact

В Preact подписка и обработка push может быть обёрнута в хук или отдельный компонент:

import { useEffect } from 'preact/hooks';

function PushManagerComponent() {
  useEffect(() => {
    async function initPush() {
      if (!('serviceWorker' in navigator) || !('PushManager' in window)) return;
      const registration = await navigator.serviceWorker.ready;
      const subscription = await registration.pushManager.getSubscription();
      if (!subscription) {
        await subscribeUser();
      }
    }
    initPush();
  }, []);

  return null; // Компонент не отображает UI
}

Особенности такого подхода:

  • Хук useEffect обеспечивает регистрацию push только один раз при монтировании.
  • Логика подписки полностью изолирована от UI, что соответствует принципам Preact о компонентах с разделением ответственности.

Особенности реализации в Preact

  • Лёгкая интеграция с состоянием приложения через хуки. Например, можно хранить информацию о подписке в глобальном состоянии или в context.
  • Минимальный размер фреймворка снижает накладные расходы на загрузку страницы, что важно для страниц с push уведомлениями.
  • Возможность использовать асинхронные операции без блокировки рендеринга UI благодаря архитектуре виртуального DOM.

Push уведомления в Preact строятся на стандартных веб-API, а архитектура компонентов позволяет организовать подписку и обработку уведомлений гибко и структурировано. Использование Service Worker, PushManager и Notification API обеспечивает надёжную доставку сообщений пользователям, а Preact обеспечивает минимальный и эффективный фронтенд-код.