Start · Sprachen · JavaScript · Referenz · ServiceWorkerGlobalScope: activate

ServiceWorkerGlobalScope: activate

Ereignis

Wird im Service Worker ausgelöst, wenn eine <code>ServiceWorkerRegistration</code> einen neuen aktiven Worker bekommt. Das ist der typische Ort zum Aufräumen alter Caches.

seit JavaScript Baseline: alle modernen Browser (seit 2018) Kategorie: webapi

Signatur

self.addEventListener("activate", handler)

Beschreibung

Der activate-Event wird im globalen Bereich eines Service Workers (ServiceWorkerGlobalScope) ausgelöst, sobald der Worker zum aktiven Worker seiner Registrierung wird. Er kommt im Lebenszyklus nach install. Ein neu installierter Worker wird allerdings erst aktiviert, wenn keine Seite mehr vom alten Worker gesteuert wird – es sei denn, man ruft self.skipWaiting() auf.

Das Event-Objekt ist ein ExtendableEvent. Mit event.waitUntil(promise) hält man die Aktivierungsphase offen, bis asynchrone Aufgaben erledigt sind. Dazu gehören vor allem das Löschen veralteter Caches, das Migrieren von IndexedDB-Schemata oder das Aktivieren von Navigation Preload. Solange das Promise nicht erfüllt ist, stellt der Browser fetch- und andere funktionale Events zurück.

Einen Listener registriert man entweder mit self.addEventListener("activate", handler) oder über die Eigenschaft self.onactivate = handler. Mit self.clients.claim() übernimmt der frisch aktivierte Worker sofort alle offenen Seiten seines Gültigkeitsbereichs (Scope), statt erst beim nächsten Neuladen.

Parameter

Name Typ Default Beschreibung
$type Pflicht string Der Event-Name "activate".
$handler Pflicht (event: ExtendableEvent) => void Callback-Funktion, die ein ExtendableEvent erhält. Mit event.waitUntil() kann sie die Aktivierung verlängern.
$options boolean | AddEventListenerOptions false Optionale Listener-Optionen wie once oder signal.

Rückgabewert

Typ
void
Beschreibung
addEventListener gibt nichts zurück. Der Handler bekommt ein ExtendableEvent übergeben.

Beispiele

Alte Caches beim Aktivieren löschen

// sw.js
const CACHE_VERSION = 'app-v3';

self.addEventListener('activate', (event) => {
  event.waitUntil((async () => {
    const keys = await caches.keys();
    await Promise.all(
      keys
        .filter((key) => key !== CACHE_VERSION)
        .map((key) => caches.delete(key))
    );
    console.log('Aufgeräumt, aktiver Cache:', CACHE_VERSION);
  })());
});
Aufgeräumt, aktiver Cache: app-v3

Sofort alle Seiten übernehmen (skipWaiting + clients.claim)

// sw.js
self.addEventListener('install', () => {
  // Wartephase überspringen
  self.skipWaiting();
});

self.addEventListener('activate', (event) => {
  event.waitUntil(self.clients.claim());
});

// Seite (main.js): Wechsel des steuernden Workers bemerken
navigator.serviceWorker.addEventListener('controllerchange', () => {
  console.log('Neuer Service Worker steuert jetzt diese Seite');
});
Neuer Service Worker steuert jetzt diese Seite

Navigation Preload über die onactivate-Eigenschaft aktivieren

// sw.js
self.onactivate = (event) => {
  event.waitUntil((async () => {
    if (self.registration.navigationPreload) {
      await self.registration.navigationPreload.enable();
      console.log('Navigation Preload aktiv');
    }
  })());
};
Navigation Preload aktiv

Listener mit AbortSignal wieder entfernen

// sw.js
const controller = new AbortController();

const onActivate = (event) => {
  console.log('activate empfangen');
};

self.addEventListener('activate', onActivate, { signal: controller.signal });

// Alternativ: removeEventListener
// self.removeEventListener('activate', onActivate);
controller.abort();

// Wichtig · Fallstricke

  • Wartephase: Ein neuer Worker bleibt im Zustand waiting, solange noch ein Tab vom alten Worker gesteuert wird. Ein einfaches Neuladen reicht dafür oft nicht aus. Erst wenn alle Tabs geschlossen sind oder skipWaiting() aufgerufen wurde, wird activate ausgelöst.
  • Listener synchron registrieren: Event-Listener müssen beim ersten Auswerten des Skripts auf oberster Ebene registriert werden, nicht in einem setTimeout oder nach einem await.
  • waitUntil() muss synchron im Handler aufgerufen werden. Ein späterer Aufruf, etwa nach einem await, wirft einen InvalidStateError.
  • Wird das an waitUntil() übergebene Promise abgelehnt, bleibt der Worker trotzdem aktiv (anders als bei install). Fehler sollte man deshalb selbst behandeln und protokollieren.
  • Lange Aufgaben in activate verzögern alle fetch-Events. Die Arbeit sollte daher kurz bleiben.
  • skipWaiting() zusammen mit clients.claim() kann dazu führen, dass eine bereits geladene Seite mit altem HTML auf neue Cache-Inhalte trifft. Das braucht eine durchdachte Versionierung.
  • Service Worker laufen nur in sicheren Kontexten (HTTPS oder localhost). In Firefox sind sie im privaten Modus je nach Version nicht verfügbar.