Signatur
Beschreibung
Über das message-Ereignis des ServiceWorkerContainer (erreichbar über navigator.serviceWorker) empfängt eine Seite Nachrichten, die ein Service Worker mit Client.postMessage() an sie schickt. So kann der Worker zum Beispiel melden, dass ein Cache-Update fertig ist, dass eine neue Version bereitsteht oder dass Push-Daten angekommen sind.
Du kannst den Listener mit navigator.serviceWorker.addEventListener("message", handler) registrieren oder über die Eigenschaft navigator.serviceWorker.onmessage setzen. Der Handler bekommt ein MessageEvent. Die wichtigsten Eigenschaften:
event.data: die übertragenen Daten. Sie werden mit dem Structured-Clone-Algorithmus kopiert, deshalb funktionieren auchMap,Blob,ArrayBufferusw.event.source: dasServiceWorker-Objekt, das die Nachricht gesendet hat. Darüber kannst du direkt antworten.event.origin: der Ursprung (Origin) des Absenders.event.ports: mitgeschickteMessagePort-Objekte.
Wichtig ist die Nachrichten-Warteschlange des Clients. Nachrichten vom Service Worker werden zuerst zurückgehalten und erst zugestellt, wenn die Warteschlange aktiviert ist. Das passiert automatisch, sobald das Dokument fertig geparst ist (DOMContentLoaded), sobald onmessage gesetzt wird oder wenn du navigator.serviceWorker.startMessages() aufrufst. Ein Listener, der nur mit addEventListener registriert wurde, bekommt also vor dem Ende des Parsens noch keine Nachrichten. Dafür gehen auch keine frühen Nachrichten verloren.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $type Pflicht | string | Der Ereignistyp, hier immer "message". |
|
| $listener Pflicht | (event: MessageEvent) => void | EventListenerObject | Die Rückruffunktion, die für jede eingehende Nachricht aufgerufen wird. Sie erhält ein MessageEvent mit data, source, origin und ports. |
|
| $options | boolean | AddEventListenerOptions | false | Optionen wie once, signal (zum Entfernen über einen AbortController) oder capture. |
Rückgabewert
addEventListener() hat keinen Rückgabewert. Der Handler selbst bekommt ein MessageEvent.Beispiele
Service Worker schickt eine Nachricht an alle Tabs, die Seite empfängt sie
// sw.js: an alle kontrollierten Fenster senden
self.addEventListener("activate", (event) => {
event.waitUntil((async () => {
const clients = await self.clients.matchAll({ type: "window" });
for (const client of clients) {
client.postMessage({ type: "SW_ACTIVATED", version: "2.1.0" });
}
})());
});
// main.js: auf der Seite empfangen
navigator.serviceWorker.addEventListener("message", (event) => {
const { type, version } = event.data;
if (type === "SW_ACTIVATED") {
console.log(`Neuer Service Worker aktiv: ${version}`);
}
});
Mit onmessage empfangen und über event.source antworten
// main.js: onmessage aktiviert die Warteschlange sofort
navigator.serviceWorker.onmessage = (event) => {
if (event.data?.type === "PING") {
console.log("Ping vom Service Worker erhalten");
// event.source ist das ServiceWorker-Objekt des Absenders
event.source?.postMessage({ type: "PONG", time: Date.now() });
}
};
// sw.js
self.addEventListener("message", (event) => {
if (event.data?.type === "PONG") {
console.log("Antwort vom Client:", event.data.time);
}
});
Frühe Nachrichten mit startMessages() empfangen und Listener wieder entfernen
const onUpdate = (event) => {
if (event.data?.type === "CACHE_UPDATED") {
console.log("Aktualisiert:", event.data.url);
// Nach der ersten Aktualisierung nicht mehr zuhören
navigator.serviceWorker.removeEventListener("message", onUpdate);
}
};
navigator.serviceWorker.addEventListener("message", onUpdate);
// Nachrichten schon vor DOMContentLoaded zustellen lassen
navigator.serviceWorker.startMessages();
Listener mit AbortController aufräumen (z. B. in einer SPA-Komponente)
const controller = new AbortController();
navigator.serviceWorker.addEventListener(
"message",
(event) => {
console.log("Nachricht:", event.data);
},
{ signal: controller.signal }
);
// Später, etwa beim Verlassen der Komponente:
controller.abort(); // entfernt den Listener
// Wichtig · Fallstricke
- Nachrichten-Warteschlange: Mit
addEventListenerkommen Nachrichten erst nachDOMContentLoadedan. Wenn du sie früher brauchst, rufenavigator.serviceWorker.startMessages()auf oder setzeonmessage. Das Setzen vononmessageruftstartMessages()automatisch auf. - Richtung verwechselt: Dieses Ereignis läuft auf der Seite. Nachrichten von der Seite an den Worker kommen im Service Worker als
message-Ereignis aufselfan (ExtendableMessageEvent). Gesendet werden sie mitnavigator.serviceWorker.controller.postMessage()oderregistration.active.postMessage(). controllerkannnullsein: Beim ersten Laden und nach einem harten Neuladen (Shift+Reload) wird die Seite nicht kontrolliert. Dann schickt der Worker ihr nur Nachrichten, wenn er sie gezielt anspricht, etwa überclients.matchAll({ includeUncontrolled: true })oder nachclients.claim().- Nicht serialisierbare Daten: Funktionen, DOM-Knoten oder Objekte mit Prototyp-Logik lassen sich nicht übertragen. Schlägt die Deserialisierung fehl, wird statt
messagedas Ereignismessageerrorausgelöst. - Sicherheit: Behandle
event.datanicht ungeprüft als HTML (z. B. perinnerHTML). Prüfe am besten einentype-Schlüssel. Service Worker sind immer gleichen Ursprungs, trotzdem ist eine Prüfung auf ein festes Nachrichtenformat sinnvoll. - Verfügbarkeit:
navigator.serviceWorkergibt es nur in sicheren Kontexten (HTTPS oderlocalhost). In manchen privaten Modi, z. B. im privaten Modus von Firefox, ist esundefined. Prüfe das vorher mitif (\"serviceWorker\" in navigator).