Signatur
Beschreibung
Das Interface SharedWorker steht für einen Hintergrund-Thread, den sich mehrere Browserkontexte teilen: mehrere Tabs, Fenster, iframes oder sogar andere Worker. Voraussetzung ist, dass alle denselben Ursprung (Protokoll, Host und Port) haben. Anders als bei einem dedizierten Worker startet der Browser pro Kombination aus Skript-URL und Name nur eine Instanz. Diese Instanz läuft so lange, wie mindestens ein Kontext mit ihr verbunden ist.
Die Kommunikation läuft nicht direkt über das Worker-Objekt, sondern über die Eigenschaft port, einen MessagePort. Im Worker-Skript meldet das Ereignis connect jede neue Verbindung. Der zugehörige Port steht in event.ports[0]. So kann der Worker jeden verbundenen Client einzeln ansprechen oder Nachrichten an alle weiterleiten.
Typische Einsatzfälle:
- eine gemeinsame WebSocket-Verbindung für alle offenen Tabs, statt pro Tab eine eigene
- ein zentraler Zustand oder Cache, der sich zwischen Tabs synchron hält
- Koordination zwischen Tabs, etwa Sperren, eine Leader-Wahl oder ein gemeinsames Logging
- aufwendige Berechnungen, die nur einmal statt pro Tab laufen sollen
Das Interface erbt von EventTarget. Außer port stellt es das Ereignis error bereit, das eintritt, wenn im Worker ein Fehler auftritt.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $aURL Pflicht | string | URL | URL des Worker-Skripts. Sie muss denselben Ursprung wie das aufrufende Dokument haben (Same-Origin-Policy). | |
| $options | string | { name?: string, type?: 'classic' | 'module', credentials?: 'omit' | 'same-origin' | 'include' } | { type: 'classic', credentials: 'same-origin' } | Entweder ein name als String oder ein Optionsobjekt. name kennzeichnet die Instanz: Gleiche URL und gleicher Name ergeben denselben Worker. type: 'module' lädt das Skript als ES-Modul. credentials legt fest, ob beim Laden eines Modul-Workers Anmeldedaten mitgeschickt werden. |
Rückgabewert
SharedWorker-Objekt. Über seine Eigenschaft port (ein MessagePort) werden Nachrichten mit dem Worker ausgetauscht.Beispiele
SharedWorker erzeugen und Nachrichten austauschen
// main.js – läuft in jedem Tab
const worker = new SharedWorker('/shared-counter.js', { name: 'counter' });
worker.port.addEventListener('message', (event) => {
console.log('Zähler vom Worker:', event.data);
});
// Bei addEventListener muss der Port explizit gestartet werden
worker.port.start();
worker.port.postMessage({ type: 'increment' });
Worker-Skript: Verbindungen verwalten und an alle senden
// shared-counter.js
let count = 0;
const ports = new Set();
self.addEventListener('connect', (event) => {
const port = event.ports[0];
ports.add(port);
// onmessage startet den Port automatisch
port.onmessage = ({ data }) => {
if (data.type === 'increment') {
count += 1;
// Neuen Stand an alle verbundenen Tabs senden
for (const p of ports) p.postMessage(count);
}
if (data.type === 'bye') {
ports.delete(port);
}
};
});
Eine WebSocket-Verbindung für alle Tabs
// socket-worker.js (als Modul geladen)
const clients = new Set();
const socket = new WebSocket('wss://example.com/live');
socket.addEventListener('message', ({ data }) => {
for (const port of clients) port.postMessage(data);
});
self.onconnect = ({ ports: [port] }) => {
clients.add(port);
port.onmessage = ({ data }) => {
if (socket.readyState === WebSocket.OPEN) socket.send(data);
};
};
// main.js
if ('SharedWorker' in window) {
const worker = new SharedWorker(new URL('./socket-worker.js', import.meta.url), { type: 'module' });
worker.port.onmessage = ({ data }) => console.log('Live-Update:', data);
worker.onerror = (err) => console.error('Worker-Fehler:', err.message);
window.addEventListener('beforeunload', () => worker.port.close());
} else {
console.warn('SharedWorker nicht verfügbar – Rückfall auf eigenen WebSocket je Tab');
}
// Wichtig · Fallstricke
- Browser-Unterstützung: Chrome, Edge, Firefox und Safari (ab 16) unterstützen
SharedWorkerauf dem Desktop. Chrome für Android bietet es erst ab Version 144 an, frühere Versionen nicht. Deshalb vorher mit'SharedWorker' in windowprüfen und einen Rückfall vorsehen, etwa einen normalenWorkeroder einenBroadcastChannel. Ob Samsung Internet und Android WebView es unterstützen, bitte aktuell nachprüfen. - Port starten: Wer
addEventListener('message', …)verwendet, mussport.start()aufrufen. Das Setzen vonport.onmessagestartet den Port dagegen automatisch. - Identität der Instanz: URL, Name und Ursprung legen fest, welche Instanz verwendet wird. Unterscheidet sich die URL auch nur im Query-String, entsteht ein neuer Worker. Wird dieselbe URL und derselbe Name mit einem anderen
typeaufgerufen, löst das einen Fehler aus. - Keine Meldung beim Trennen: Wird ein Tab geschlossen, meldet der Browser das dem Worker nicht zuverlässig. Deshalb sollten Clients eine Abmeldenachricht senden oder regelmäßige Lebenszeichen verwenden, damit tote Ports aus der Liste entfernt werden. Andernfalls wächst die Liste immer weiter.
- Speicherpartitionierung: Moderne Browser trennen Instanzen zusätzlich nach der Top-Level-Seite. Ein iframe von
a.comaufb.comteilt sich den Worker also nicht mit einem Tab, der direkta.comgeöffnet hat. Im privaten Modus ist die Instanz ebenfalls getrennt. - Kein DOM-Zugriff: Wie in jedem Worker gibt es kein
documentund keinwindow. Verfügbar sindfetch,WebSocket,IndexedDBund ähnliche APIs. - Sicherheit: Da alle Tabs desselben Ursprungs den Worker erreichen können, sollten eingehende Nachrichten geprüft werden. Sensible Daten sollten nicht ungefiltert an alle Ports verteilt werden. Die Direktive
worker-srcder Content Security Policy (CSP) muss das Worker-Skript erlauben. - Fehlersuche: In Chrome findet man Shared Worker unter
chrome://inspect/#workers, in Firefox unterabout:debugging.