Push-уведомления предоставляют возможность отправки сообщений пользователю даже тогда, когда веб-приложение не активно в браузере. В сочетании с современными фреймворками, такими как Lit, это позволяет создавать интерактивные и динамичные интерфейсы с минимальными затратами ресурсов.
Для реализации Push-уведомлений необходим сервис-воркер, который
работает в фоне и обрабатывает входящие уведомления. В Lit-проектах
сервис-воркер регистрируется стандартным образом через
navigator.serviceWorker:
if ('serviceWorker' in navigator) {
navigator.serviceWorker.register('/service-worker.js')
.then(registration => {
console.log('Service Worker зарегистрирован с областью:', registration.scope);
})
.catch(error => {
console.error('Ошибка регистрации Service Worker:', error);
});
}
Сервис-воркер обеспечивает обработку событий push и
notificationclick, что позволяет управлять отображением
уведомлений и действиями пользователя.
Push API предоставляет методы для подписки на уведомления и
взаимодействия с сервером. Подписка создается через объект
PushManager, доступный через зарегистрированный
сервис-воркер:
async function subscribeUser() {
const registration = await navigator.serviceWorker.ready;
try {
const subscription = await registration.pushManager.subscribe({
userVisibleOnly: true,
applicationServerKey: urlBase64ToUint8Array('YOUR_PUBLIC_VAPID_KEY')
});
console.log('Подписка на Push уведомления:', subscription);
// Отправка подписки на сервер
await fetch('/subscribe', {
method: 'POST',
body: JSON.stringify(subscription),
headers: { 'Content-Type': 'application/json' }
});
} catch (error) {
console.error('Ошибка подписки:', error);
}
}
Ключевой момент: userVisibleOnly: true
обязательный параметр, обеспечивающий отображение уведомлений
пользователю.
Lit позволяет интегрировать логику Push-уведомлений непосредственно в
компоненты через жизненные циклы и реактивные свойства. Например, можно
создать компонент push-button, который инициирует
подписку:
import { LitElement, html, css } from 'lit';
class PushButton extends LitElement {
static styles = css`
button {
padding: 0.5rem 1rem;
font-size: 1rem;
cursor: pointer;
}
`;
render() {
return html`
<button @click=${this.subscribe}>Подписаться на уведомления</button>
`;
}
async subscribe() {
if ('serviceWorker' in navigator && 'PushManager' in window) {
const registration = await navigator.serviceWorker.ready;
const subscription = await registration.pushManager.subscribe({
userVisibleOnly: true,
applicationServerKey: urlBase64ToUint8Array('YOUR_PUBLIC_VAPID_KEY')
});
await fetch('/subscribe', {
method: 'POST',
body: JSON.stringify(subscription),
headers: { 'Content-Type': 'application/json' }
});
console.log('Успешная подписка на уведомления');
} else {
console.warn('Push уведомления не поддерживаются этим браузером');
}
}
}
customElements.define('push-button', PushButton);
Сервис-воркер перехватывает события push и отображает уведомления
через API showNotification:
self.addEventListener('push', event => {
const data = event.data.json();
const options = {
body: data.body,
icon: '/icons/notification-icon.png',
badge: '/icons/badge.png',
data: { url: data.url }
};
event.waitUntil(
self.registration.showNotification(data.title, options)
);
});
self.addEventListener('notificationclick', event => {
event.notification.close();
event.waitUntil(
clients.openWindow(event.notification.data.url)
);
});
Особенности реализации:
event.waitUntil гарантирует, что сервис-воркер не
завершит выполнение до завершения обработки уведомления.data можно передавать любые данные для дальнейшей
обработки при клике.Серверная логика обычно реализуется с использованием VAPID-ключей для
аутентификации и Web Push библиотек, таких как web-push на
Node.js:
import webPush from 'web-push';
const vapidKeys = {
publicKey: 'YOUR_PUBLIC_VAPID_KEY',
privateKey: 'YOUR_PRIVATE_VAPID_KEY'
};
webPush.setVapidDetails(
'mailto:admin@example.com',
vapidKeys.publicKey,
vapidKeys.privateKey
);
const sendNotification = (subscription, payload) => {
webPush.sendNotification(subscription, JSON.stringify(payload))
.then(() => console.log('Уведомление отправлено'))
.catch(err => console.error('Ошибка отправки уведомления', err));
};
Payload содержит данные, которые будут отображены пользователю, включая текст, иконку и ссылки для действий.
Lit позволяет связывать состояние компонента с уведомлениями. Например, можно хранить статус подписки в реактивном свойстве и отображать соответствующий интерфейс:
static properties = {
subscribed: { type: Boolean }
};
async connectedCallback() {
super.connectedCallback();
const registration = await navigator.serviceWorker.ready;
const subscription = await registration.pushManager.getSubscription();
this.subscribed = !!subscription;
}
Реактивное обновление интерфейса обеспечивает мгновенное отражение изменений, например, смену кнопки с «Подписаться» на «Вы подписаны».
ServiceWorker и
PushManager.Notification API без
участия сервера.actions) в
уведомлениях.Использование Lit в сочетании с Push API позволяет создавать современные, динамичные веб-приложения, где уведомления становятся не просто уведомлением, а частью интерактивного интерфейса с гибкой реактивной логикой.