Signatur
Beschreibung
Die Schnittstelle ContentIndex gehört zur Content Index API. Eine Progressive Web App kann damit dem Browser mitteilen, welche Inhalte sie bereits für die Offline-Nutzung zwischengespeichert hat. Chrome für Android zeigt diese Einträge zum Beispiel im Bereich „Artikel für dich“ bzw. unter den Downloads an. So finden Nutzer offline lesbare Artikel oder gespeicherte Videos auch dann, wenn sie die App gerade nicht geöffnet haben.
Es gibt keinen Konstruktor. Du erreichst die Instanz über die Eigenschaft index einer ServiceWorkerRegistration, also im Fenster über navigator.serviceWorker.ready und im Service Worker über self.registration.index. Die Schnittstelle hat drei Methoden:
add(description): registriert einen Inhalt. GibtPromise<undefined>zurück. Existiert dieidschon, wird der Eintrag ersetzt.delete(id): entfernt einen Eintrag. GibtPromise<undefined>zurück.getAll(): liefertPromise<ContentDescription[]>mit allen registrierten Einträgen.
Die API ersetzt keinen Cache, sie ist nur ein Verzeichnis. Die eigentlichen Daten musst du selbst ablegen, etwa mit der Cache API oder in IndexedDB. Löscht der Nutzer einen Eintrag in der Browser-Oberfläche, bekommt der Service Worker das Ereignis contentdelete. Dort solltest du die zugehörigen Daten aus dem Cache entfernen.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $description Pflicht | ContentDescription (Object) | Argument von add(): ein Objekt, das den Inhalt beschreibt. Seine Felder stehen in den folgenden Zeilen. |
|
| $description.id Pflicht | string | Eindeutige Kennung des Eintrags. Dieselbe Kennung brauchst du später für delete(id). |
|
| $description.title Pflicht | string | Titel, den der Browser anzeigt. | |
| $description.description Pflicht | string | Kurzbeschreibung des Inhalts. | |
| $description.url Pflicht | string | URL des Inhalts. Sie muss zur selben Herkunft gehören, im Geltungsbereich des Service Workers liegen und offline funktionieren. | |
| $description.category | '' | 'homepage' | 'article' | 'video' | 'audio' | '' | Art des Inhalts. Der Browser kann danach gruppieren. |
| $description.icons | Array<{src: string, sizes?: string, type?: string}> | [] | Vorschaubilder im Format der Icons aus dem Web-App-Manifest. |
| $id Pflicht | string | Argument von delete(): die Kennung des Eintrags, der entfernt werden soll. |
Beispiele
Unterstützung prüfen und einen offline gespeicherten Artikel registrieren
const speichereArtikelOffline = async (artikel) => {
const registration = await navigator.serviceWorker.ready;
// Funktionserkennung: die API gibt es nur in Chromium
if (!('index' in registration)) {
console.log('Content Index API wird nicht unterstützt');
return;
}
// Zuerst die Seite wirklich cachen, sonst lehnt add() ab
const cache = await caches.open('artikel-v1');
await cache.add(artikel.url);
await registration.index.add({
id: `artikel-${artikel.slug}`,
title: artikel.titel,
description: artikel.teaser,
category: 'article',
url: artikel.url,
icons: [{ src: '/img/artikel-192.png', sizes: '192x192', type: 'image/png' }]
});
console.log('Registriert:', artikel.titel);
};
speichereArtikelOffline({
slug: 'promises-erklaert',
titel: 'Promises verständlich erklärt',
teaser: 'Grundlagen zu then, catch und async/await',
url: '/artikel/promises-erklaert'
});
Alle registrierten Inhalte auflisten
const zeigeOfflineInhalte = async () => {
const registration = await navigator.serviceWorker.ready;
if (!('index' in registration)) return [];
const eintraege = await registration.index.getAll();
for (const { id, title, category } of eintraege) {
console.log(`${id} [${category}]: ${title}`);
}
return eintraege;
};
zeigeOfflineInhalte();
Eintrag löschen und auf Löschung durch den Nutzer reagieren (Service Worker)
// In der Seite: Eintrag und Cache-Daten gemeinsam entfernen
const entferneArtikel = async (id, url) => {
const registration = await navigator.serviceWorker.ready;
await registration.index.delete(id);
const cache = await caches.open('artikel-v1');
await cache.delete(url);
};
// In sw.js: Der Nutzer hat den Eintrag in der Browser-Oberfläche gelöscht
self.addEventListener('contentdelete', (event) => {
// event.id enthält die Kennung des gelöschten Eintrags
const slug = event.id.replace('artikel-', '');
event.waitUntil(
caches.open('artikel-v1').then((cache) => cache.delete(`/artikel/${slug}`))
);
});
// Wichtig · Fallstricke
- Experimentell: Die API gibt es nur in Chromium-Browsern, praktisch vor allem in Chrome für Android. Firefox und Safari unterstützen sie nicht. Prüfe die Unterstützung immer mit
'index' in registrationund behandle die API als optionale Verbesserung. - Die API läuft nur in einem sicheren Kontext (HTTPS) und nur mit einem aktiven Service Worker.
- Chrome prüft beim Aufruf von
add(), ob dieurloffline tatsächlich ausgeliefert werden kann. Kann derfetch-Handler des Service Workers die Seite offline nicht liefern, wird das Promise mit einemTypeErrorabgelehnt. Speichere die Inhalte deshalb vor dem Aufruf vonadd()im Cache. urlundiconsmüssen zur selben Herkunft gehören. Dieurlmuss außerdem im Geltungsbereich (Scope) des Service Workers liegen.- Das Verzeichnis und deine Cache-Daten laufen nicht automatisch synchron. Wenn du Cache-Einträge entfernst, rufe auch
delete()auf. Umgekehrt solltest du aufcontentdeletereagieren, sonst sieht der Nutzer tote Einträge oder es bleiben verwaiste Daten liegen. - Registriere nur Inhalte, die für Nutzer wirklich sinnvoll sind. Werbung oder Seiten mit dauernd wechselndem Inhalt gehören nicht hinein.