Push-уведомления представляют собой сообщения, которые приложение может отправлять пользователю, даже если оно не активно в данный момент. В веб-приложениях они реализуются через комбинацию Service Worker, Push API и Notification API. Polymer позволяет интегрировать эти технологии в компоненты с высокой модульностью и повторным использованием кода.
Service Worker выполняет роль фонового скрипта, который перехватывает
события push и взаимодействует с браузером. Для регистрации Service
Worker используется метод
navigator.serviceWorker.register():
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 должен находиться в корне
проекта или на уровне, позволяющем покрывать нужные URL.localhost).Для получения push-уведомлений необходимо создать подписку через
PushManager:
function subscribeUser() {
navigator.serviceWorker.ready.then(registration => {
const subscribeOptions = {
userVisibleOnly: true,
applicationServerKey: urlBase64ToUint8Array('<VAPID_PUBLIC_KEY>')
};
return registration.pushManager.subscribe(subscribeOptions);
})
.then(pushSubscription => {
console.log('Подписка создана:', JSON.stringify(pushSubscription));
});
}
Особенности:
userVisibleOnly: true гарантирует, что уведомление
всегда будет отображаться пользователю.applicationServerKey используется для аутентификации на
сервере через протокол VAPID. Этот ключ преобразуется из Base64 в
Uint8Array с помощью вспомогательной функции:function urlBase64ToUint8Array(base64String) {
const padding = '='.repeat((4 - base64String.length % 4) % 4);
const base64 = (base64String + padding).replace(/\-/g, '+').replace(/_/g, '/');
const rawData = window.atob(base64);
return Uint8Array.from([...rawData].map(char => char.charCodeAt(0)));
}
После подписки браузер может получать push-события. Service Worker
обрабатывает их с помощью слушателя push:
self.addEventListener('push', event => {
const data = event.data ? event.data.json() : {};
const title = data.title || 'Новое уведомление';
const options = {
body: data.body || 'Текст уведомления',
icon: '/icons/notification-icon.png',
badge: '/icons/notification-badge.png',
data: data.url || '/'
};
event.waitUntil(
self.registration.showNotification(title, options)
);
});
Основные аспекты:
showNotification отвечает за отображение
уведомления.data позволяет передавать дополнительную
информацию, например ссылку для открытия при клике.Для реализации навигации при клике на уведомление используется
событие notificationclick:
self.addEventListener('notificationclick', event => {
event.notification.close();
event.waitUntil(
clients.matchAll({ type: 'window', includeUncontrolled: true }).then(clientList => {
const url = event.notification.data;
for (const client of clientList) {
if (client.url === url && 'focus' in client) return client.focus();
}
if (clients.openWindow) return clients.openWindow(url);
})
);
});
Важные моменты:
close().В Polymer push-уведомления удобно инкапсулировать в отдельный
элемент. Пример простого элемента push-manager:
import {PolymerElement, html} from '@polymer/polymer/polymer-element.js';
class PushManagerElement extends PolymerElement {
static get template() {
return html`<button on-click="subscribeUser">Подписаться на уведомления</button>`;
}
subscribeUser() {
if (!('serviceWorker' in navigator) || !('PushManager' in window)) return;
navigator.serviceWorker.ready.then(registration => {
registration.pushManager.subscribe({
userVisibleOnly: true,
applicationServerKey: urlBase64ToUint8Array('<VAPID_PUBLIC_KEY>')
}).then(subscription => {
console.log('Подписка создана:', JSON.stringify(subscription));
// Здесь можно отправить subscription на сервер
});
});
}
}
customElements.define('push-manager-element', PushManagerElement);
Преимущества такого подхода:
Для отправки push-сообщений сервер использует подписку пользователя.
На Node.js это реализуется через библиотеку web-push:
const webPush = require('web-push');
webPush.setVapidDetails(
'mailto:example@domain.com',
'<VAPID_PUBLIC_KEY>',
'<VAPID_PRIVATE_KEY>'
);
const pushSubscription = { /* объект подписки пользователя */ };
const payload = JSON.stringify({ title: 'Привет', body: 'Новое уведомление' });
webPush.sendNotification(pushSubscription, payload)
.then(response => console.log('Уведомление отправлено', response))
.catch(error => console.error('Ошибка отправки', error));
Особенности:
Эта схема позволяет создавать надежные, масштабируемые push-уведомления в веб-приложениях на Polymer, обеспечивая современный пользовательский опыт и высокую модульность кода.