Start · Sprachen · JavaScript · Referenz · SharedWorker

SharedWorker

Schnittstelle

Ein <code>SharedWorker</code> ist ein Worker, den mehrere Browserkontexte gleichen Ursprungs (Fenster, Tabs, iframes) gemeinsam nutzen und über einen <code>MessagePort</code> ansprechen.

seit JavaScript Chrome 4+, Firefox 29+, Safari 16+; Chrome für And Kategorie: webapi

Signatur

interface SharedWorker extends EventTarget

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

Typ
SharedWorker
Beschreibung
Ein 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' });
Zähler vom Worker: 1 (im zweiten Tab: 2 usw.)

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');
}
Live-Update: {"price":42.1}

// Wichtig · Fallstricke

  • Browser-Unterstützung: Chrome, Edge, Firefox und Safari (ab 16) unterstützen SharedWorker auf dem Desktop. Chrome für Android bietet es erst ab Version 144 an, frühere Versionen nicht. Deshalb vorher mit 'SharedWorker' in window prüfen und einen Rückfall vorsehen, etwa einen normalen Worker oder einen BroadcastChannel. Ob Samsung Internet und Android WebView es unterstützen, bitte aktuell nachprüfen.
  • Port starten: Wer addEventListener('message', …) verwendet, muss port.start() aufrufen. Das Setzen von port.onmessage startet 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 type aufgerufen, 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.com auf b.com teilt sich den Worker also nicht mit einem Tab, der direkt a.com geöffnet hat. Im privaten Modus ist die Instanz ebenfalls getrennt.
  • Kein DOM-Zugriff: Wie in jedem Worker gibt es kein document und kein window. Verfügbar sind fetch, WebSocket, IndexedDB und ä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-src der Content Security Policy (CSP) muss das Worker-Skript erlauben.
  • Fehlersuche: In Chrome findet man Shared Worker unter chrome://inspect/#workers, in Firefox unter about:debugging.