JavaScript Push API und Benachrichtigungen
Die Push API in JavaScript ist ein unverzichtbares Werkzeug für Entwickler, die Web-Apps mit Echtzeit-Benachrichtigungen erweitern möchten.
Einführung in die Push API in JavaScript
Die Push API in JavaScript ermöglicht es einer Webanwendung, Nachrichten von einem Server zu empfangen, selbst wenn die Seite geschlossen ist oder der Browser im Hintergrund läuft. Sie bildet die Grundlage für Web-Push-Benachrichtigungen: Nachrichtenalarme, Chat-Nachrichten und Reaktivierungs-Hinweise, die eintreffen, ohne dass der Nutzer einen Tab geöffnet halten muss.
Die Push API funktioniert niemals allein. Sie baut auf zwei weiteren Browser-Funktionen auf:
- Einem Service Worker — einem Hintergrundskript, das nach dem Schließen der Seite aktiv bleibt und den Push empfängt.
- Der Notifications API — mit der der Service Worker die Nachricht tatsächlich dem Nutzer anzeigt.
Diese Seite behandelt den vollständigen clientseitigen Ablauf: einen Service Worker registrieren, Berechtigung anfordern, mit einem VAPID-Schlüssel abonnieren, den Push im Service Worker empfangen und eine Benachrichtigung anzeigen. Außerdem wird erklärt, welche Rolle Ihr Server dabei spielt.
Wie der Push-Ablauf funktioniert
Der vollständige Weg einer einzelnen Push-Nachricht sieht wie folgt aus:
- Ihre Seite registriert einen Service Worker und abonniert Push. Der Browser gibt ein
PushSubscription-Objekt zurück, das eine eindeutige Endpoint-URL enthält. - Ihre Seite sendet dieses Abonnement an Ihren Server und speichert es.
- Später signiert Ihr Server eine Nachricht mit seinem privaten VAPID-Schlüssel und sendet sie an den Abonnement-Endpoint, der zu einem Push-Dienst eines Anbieters gehört (Mozilla, Google, Apple usw.).
- Der Push-Dienst weckt den Browser des Nutzers auf und löst ein
push-Ereignis in Ihrem Service Worker aus. - Der Service Worker zeigt eine Benachrichtigung als Reaktion an.
Die Push API erfordert einen sicheren Kontext: Die Seite muss über HTTPS ausgeliefert werden (localhost gilt für die Entwicklung als sicher). Ohne HTTPS sind navigator.serviceWorker und PushManager nicht verfügbar.
Push-Benachrichtigungen implementieren
Service Worker einrichten
Zunächst müssen wir einen Service Worker registrieren, der die Hintergrundaufgaben für Push-Benachrichtigungen übernimmt:
// Registering a service worker
if ('serviceWorker' in navigator) {
navigator.serviceWorker.register('/service-worker.js')
.then(function(registration) {
console.log('Service Worker registered with scope:', registration.scope);
}).catch(function(error) {
console.log('Service Worker registration failed:', error);
});
}Berechtigung für Benachrichtigungen anfordern
Vor dem Senden von Benachrichtigungen muss die Erlaubnis des Nutzers eingeholt werden. Die Anfrage muss durch eine Nutzeraktion ausgelöst werden (z. B. einen Klick) — Browser lehnen Berechtigungsanfragen ab, die beim Laden der Seite automatisch erscheinen:
<button id="enable-notif-btn">Enable Notifications</button>
<script>
// Asking user permission for notifications
function requestPermission() {
Notification.requestPermission().then(function(permission) {
console.log('Notification permission:', permission);
});
}
document.getElementById('enable-notif-btn').addEventListener('click', requestPermission);
</script>Push-Benachrichtigungen abonnieren
Nach der Erteilung der Berechtigung kann die Anwendung Push-Benachrichtigungen abonnieren. Der applicationServerKey muss ein Uint8Array sein, nicht der base64-String, den Sie üblicherweise speichern — konvertieren Sie ihn daher zuerst. VAPID (Voluntary Application Server Identification) ist das Schlüsselpaar, mit dem der Push-Dienst verifiziert, dass Pushes wirklich von Ihrem Server stammen: Der öffentliche Schlüssel kommt hier rein, der private bleibt auf Ihrem Backend.
<button id="subscribe-btn">Subscribe to Push Notifications</button>
<script>
// The VAPID public key arrives as a base64url string; the API needs a Uint8Array.
function urlBase64ToUint8Array(base64String) {
const padding = '='.repeat((4 - (base64String.length % 4)) % 4);
const base64 = (base64String + padding).replace(/-/g, '+').replace(/_/g, '/');
const raw = atob(base64);
return Uint8Array.from([...raw].map(c => c.charCodeAt(0)));
}
const VAPID_PUBLIC_KEY = 'YOUR_VAPID_PUBLIC_KEY'; // base64url string from your server
function subscribeToPush() {
navigator.serviceWorker.ready.then(function(registration) {
// userVisibleOnly: true is required — the browser rejects silent push subscriptions.
return registration.pushManager.subscribe({
userVisibleOnly: true,
applicationServerKey: urlBase64ToUint8Array(VAPID_PUBLIC_KEY)
});
})
.then(function(subscription) {
console.log('Push subscription:', JSON.stringify(subscription));
// Send the subscription to your backend so it can push to this user later.
return fetch('/api/save-subscription', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(subscription)
});
})
.catch(function(error) {
console.log('Failed to subscribe to push:', error);
});
}
document.getElementById('subscribe-btn').addEventListener('click', subscribeToPush);
</script>Ein PushSubscription-Objekt serialisiert zu JSON und enthält die endpoint-URL sowie die Verschlüsselungs-keys (p256dh und auth). Ihr Server benötigt all diese Angaben, um eine Nachricht zu senden. Das Setzen von userVisibleOnly: true ist in aktuellen Browsern Pflicht: Es verspricht, dass jeder Push zu einer für den Nutzer sichtbaren Benachrichtigung führt — deshalb sind stille Hintergrund-Pushes im Web nicht erlaubt.
Eingehende Push-Nachrichten verarbeiten
Um eingehende Nachrichten zu verarbeiten, lauscht der Service Worker auf push-Ereignisse. Die gesendete Nutzlast kommt über event.data an; lesen Sie sie mit event.data.json() (oder .text()). Das Einbetten von showNotification() in event.waitUntil() hält den Service Worker am Leben, bis die Benachrichtigung angezeigt wurde:
// Inside service-worker.js
self.addEventListener('push', function(event) {
// Read the payload your server sent (fall back gracefully if there is none).
var payload = event.data ? event.data.json() : {};
var options = {
body: payload.body || 'New notification.',
icon: 'icon.png',
vibrate: [100, 50, 100],
data: { primaryKey: 1 }
};
event.waitUntil(
self.registration.showNotification(payload.title || 'Push Notification', options)
);
});
self.addEventListener('notificationclick', function(event) {
event.notification.close();
event.waitUntil(
clients.openWindow('https://example.com')
);
});
self.addEventListener('pushsubscriptionchange', function(event) {
console.log('Subscription changed, re-subscribing...');
// Re-subscribe using the same parameters
event.registration.pushManager.subscribe({
userVisibleOnly: true,
applicationServerKey: 'YOUR_VAPID_PUBLIC_KEY'
}).then(function(newSubscription) {
console.log('Re-subscribed:', newSubscription);
}).catch(function(error) {
console.error('Re-subscription failed:', error);
});
});Dieses Beispiel zeigt die drei wichtigen Ereignisse: push (Benachrichtigung anzeigen), notificationclick (Fenster fokussieren oder öffnen, wenn der Nutzer klickt) und pushsubscriptionchange (erneut abonnieren, wenn der Browser das Abonnement erneuert).
Die Rolle des Servers
Der Browser kann sich nicht selbst pushen — jede Nachricht stammt von Ihrem Backend. Der Server verwahrt den privaten VAPID-Schlüssel und sendet für jedes gespeicherte Abonnement eine verschlüsselte, signierte HTTP-Anfrage an den endpoint des Abonnements. In der Praxis nutzt man eine Web-Push-Bibliothek (zum Beispiel web-push für Node.js), anstatt die Verschlüsselung von Hand zu implementieren:
// Server side (Node.js) — conceptual example
const webpush = require('web-push');
webpush.setVapidDetails(
'mailto:[email protected]',
process.env.VAPID_PUBLIC_KEY,
process.env.VAPID_PRIVATE_KEY
);
// `subscription` is the JSON object the browser sent to /api/save-subscription
const payload = JSON.stringify({ title: 'Hello', body: 'You have a new message.' });
webpush.sendNotification(subscription, payload)
.catch(err => console.error('Push failed:', err.statusCode));Eine 410 Gone- oder 404-Antwort bedeutet, dass das Abonnement abgelaufen ist — löschen Sie es aus Ihrer Datenbank. Dies ist das serverseitige Gegenstück zur Behandlung von pushsubscriptionchange auf dem Client.
Best Practices für Push-Benachrichtigungen
- Nutzerengagement: Gestalten Sie Benachrichtigungen so, dass sie zeitgemäß, relevant und präzise sind.
- Datenschutzkonformität: Stellen Sie immer sicher, dass die Einwilligung des Nutzers eingeholt wurde, bevor Benachrichtigungen versendet werden.
- Performance: Steuern Sie Häufigkeit und Zeitpunkt von Benachrichtigungen, um den Nutzer nicht zu überlasten.
- Abonnementverlängerung: Push-Abonnements laufen regelmäßig ab. Implementieren Sie clientseitige Logik, um den Abonnementstatus zu prüfen und bei Bedarf neu zu abonnieren, oder behandeln Sie Ablaufereignisse aus dem Service Worker.
Fazit
Die Push API öffnet einen Kanal für die direkte Interaktion mit Nutzern und bietet ein leistungsstarkes Werkzeug für mehr Engagement. Durch den Einsatz dieser API können Entwickler eine dynamischere und reaktionsfähigere Nutzererfahrung bieten. Eine korrekte Implementierung von Push-Benachrichtigungen kann die Funktionalität und Attraktivität von Webanwendungen erheblich steigern und Nutzer informiert und engagiert halten.