Signatur
Beschreibung
Worklet ist die abstrakte Basisschnittstelle für kleine, stark eingeschränkte Skriptumgebungen. Sie laufen unabhängig vom Haupt-Thread und hängen sich in eine bestimmte Stufe der Browser-Pipeline ein, etwa die Audioverarbeitung oder das Zeichnen. Anders als ein Worker erzeugt man ein Worklet nicht selbst mit new. Der Browser stellt feste Instanzen bereit, zum Beispiel audioContext.audioWorklet oder CSS.paintWorklet.
Die Schnittstelle hat genau eine Methode: addModule(moduleURL, options). Sie lädt ein ES-Modul in den globalen Bereich des Worklets (WorkletGlobalScope) und gibt ein Promise zurück. Das Promise wird erfüllt, sobald das Modul geladen und ausgeführt ist. Im Modul registriert man dann Klassen, zum Beispiel mit registerProcessor() (Audio) oder registerPaint() (CSS Painting API).
Die wichtigsten Unterklassen bzw. Einsatzgebiete:
- AudioWorklet: eigene Audioverarbeitung mit geringer Latenz im Audio-Rendering-Thread. Diese Variante wird von allen Browsern unterstützt.
- PaintWorklet (
CSS.paintWorklet): eigene Hintergründe und Rahmen überpaint()in CSS. - AnimationWorklet und LayoutWorklet: experimentelle Houdini-APIs.
Worklet-Code ist bewusst zustandsarm gehalten. Der Browser darf mehrere globale Bereiche parallel erzeugen oder wieder verwerfen. DOM-Zugriff, fetch und setTimeout gibt es dort in der Regel nicht.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $moduleURL Pflicht | string | URL | Parameter von addModule(): URL des JavaScript-Moduls, das in den WorkletGlobalScope geladen wird. Relative Pfade werden relativ zum Dokument aufgelöst. Blob-URLs sind erlaubt. |
|
| $options | { credentials?: 'omit' | 'same-origin' | 'include' } | { credentials: 'same-origin' } | Parameter von addModule(): legt fest, ob beim Laden des Moduls Anmeldedaten (Cookies, HTTP-Authentifizierung) mitgeschickt werden. |
Rückgabewert
addModule() gibt ein Promise zurück. Es wird erfüllt, wenn das Modul geladen und ausgewertet ist. Bei einem Netzwerk- oder Syntaxfehler wird es mit einem Fehler abgelehnt (in der Regel AbortError bzw. SyntaxError).Beispiele
AudioWorklet: eigenen Gain-Prozessor laden
// gain-processor.js (läuft im AudioWorkletGlobalScope)
// class GainProcessor extends AudioWorkletProcessor {
// process(inputs, outputs) {
// const input = inputs[0], output = outputs[0];
// for (let ch = 0; ch < input.length; ch++) {
// for (let i = 0; i < input[ch].length; i++) {
// output[ch][i] = input[ch][i] * 0.5;
// }
// }
// return true; // Prozessor aktiv halten
// }
// }
// registerProcessor('gain-processor', GainProcessor);
// main.js
const startAudio = async () => {
const ctx = new AudioContext();
// ctx.audioWorklet ist eine Worklet-Instanz
await ctx.audioWorklet.addModule('gain-processor.js');
const osc = new OscillatorNode(ctx, { frequency: 440 });
const gain = new AudioWorkletNode(ctx, 'gain-processor');
osc.connect(gain).connect(ctx.destination);
osc.start();
console.log('Worklet geladen:', ctx.audioWorklet instanceof Worklet);
};
document.querySelector('#play').addEventListener('click', startAudio);
PaintWorklet: Schachbrett-Hintergrund per CSS
// checkerboard.js (läuft im PaintWorkletGlobalScope)
// registerPaint('checkerboard', class {
// paint(ctx, size) {
// const s = 16;
// for (let y = 0; y < size.height / s; y++) {
// for (let x = 0; x < size.width / s; x++) {
// ctx.fillStyle = (x + y) % 2 ? '#ddd' : '#fff';
// ctx.fillRect(x * s, y * s, s, s);
// }
// }
// }
// });
// main.js — Feature-Erkennung, weil nicht alle Browser das unterstützen
if ('paintWorklet' in CSS) {
await CSS.paintWorklet.addModule('checkerboard.js');
document.body.style.backgroundImage = 'paint(checkerboard)';
} else {
console.warn('CSS Painting API nicht verfügbar');
}
Modul aus Blob-URL laden und Fehler behandeln
const code = `
registerProcessor('silence', class extends AudioWorkletProcessor {
process() { return false; }
});
`;
const url = URL.createObjectURL(new Blob([code], { type: 'text/javascript' }));
const ctx = new AudioContext();
try {
await ctx.audioWorklet.addModule(url, { credentials: 'omit' });
console.log('Modul registriert');
} catch (err) {
console.error('Laden fehlgeschlagen:', err.name);
} finally {
URL.revokeObjectURL(url);
}
// Wichtig · Fallstricke
- Kein Konstruktor:
new Worklet()wirft einenTypeError. Man verwendet immer eine vom Browser bereitgestellte Instanz wieaudioContext.audioWorkletoderCSS.paintWorklet. - Sicherer Kontext:
addModule()funktioniert nur über HTTPS oderlocalhost. Überfile://scheitert das Laden. - CORS/CSP: Module von fremden Ursprüngen brauchen passende CORS-Header. Die CSP-Direktive
script-srcgilt auch für Worklet-Module, bei Blob-URLs mussblob:erlaubt sein. - Keine Zustandsgarantie: Der Browser kann mehrere globale Bereiche erzeugen und wieder verwerfen. Globale Variablen im Worklet sind daher kein verlässlicher Speicher.
- Kompatibilität:
AudioWorkletläuft in allen aktuellen Browsern.CSS.paintWorkletgibt es in Chromium-Browsern, in Firefox und Safari fehlt es oder ist nur eingeschränkt vorhanden. AnimationWorklet und LayoutWorklet sind experimentell. Deshalb immer per Feature-Erkennung prüfen. - Mehrfaches
addModule()mit derselben URL lädt das Modul nicht erneut. Ein zweitesregisterProcessor()mit gleichem Namen wirft dagegen einenNotSupportedError.