Die drei Dateien, konkret
Was hineingehört, im Klartext — mit dem Mindestmaß, das wirklich genügt.
Legen Sie die drei Dateien neben Ihre Anwendung, dorthin, wo sie öffentlich erreichbar sind. In einem Next.js-Projekt aus Kurs 1 ist das der Ordner public/.
Die Beschreibung: public/manifest.webmanifest
Sie sagt dem Gerät, wie die Anwendung heißt, welches Symbol sie hat und wo sie startet. Ohne sie bietet kein Gerät „Installieren“ an.
{
"name": "Rundgang",
"short_name": "Rundgang",
"start_url": "/",
"display": "standalone",
"background_color": "#16386D",
"theme_color": "#16386D",
"icons": [
{ "src": "/symbol-192.png", "sizes": "192x192", "type": "image/png" },
{ "src": "/symbol-512.png", "sizes": "512x512", "type": "image/png" },
{ "src": "/symbol-512.png", "sizes": "512x512", "type": "image/png",
"purpose": "maskable" }
]
}display: standalone ist die Zeile, die die Browserleiste verschwinden lässt. purpose: maskable erlaubt Android, das Symbol rund oder eckig zu beschneiden, ohne dass etwas Wichtiges abgeschnitten wird — dafür braucht das Bild ringsum etwa 20 % Rand.Die Verknüpfung im Kopf der Seite
Eine Zeile im <head>. In Next.js gehört sie in das Wurzel-Layout.
<link rel="manifest" href="/manifest.webmanifest" /> <meta name="theme-color" content="#16386D" /> <link rel="apple-touch-icon" href="/symbol-192.png" />
Der Zwischenspeicher: public/sw.js
Ein kleines Programm, das jede Anfrage abfängt. Diese Fassung ist bewusst die einfachste, die etwas taugt: Sie legt beim ersten Besuch das Nötigste ab und liefert es später auch ohne Netz.
const LAGER = 'rundgang-v1';
const NOETIG = ['/', '/manifest.webmanifest', '/symbol-192.png'];
self.addEventListener('install', e => {
e.waitUntil(caches.open(LAGER).then(c => c.addAll(NOETIG)));
});
self.addEventListener('activate', e => { // alte Lager aufräumen
e.waitUntil(caches.keys().then(k =>
Promise.all(k.filter(n => n !== LAGER).map(n => caches.delete(n)))));
});
self.addEventListener('fetch', e => {
if (e.request.method !== 'GET') return; // nur Lesen aus dem Lager
e.respondWith(
fetch(e.request)
.then(a => { const k = a.clone();
caches.open(LAGER).then(c => c.put(e.request, k)); return a; })
.catch(() => caches.match(e.request)) // kein Netz: aus dem Lager
);
});if (e.request.method !== 'GET') return; ist keine Kür. Ohne sie legen Sie irgendwann auch Formularabsendungen ins Lager und liefern gespeicherte Antworten auf Vorgänge aus, die nie stattgefunden haben. Ein Zwischenspeicher darf nur lesen.Anmelden — eine Zeile in der Anwendung
if ('serviceWorker' in navigator) {
navigator.serviceWorker.register('/sw.js');
}Danach: Seite laden, einmal neu laden — und Android bietet die Installation an.
localhost). Zweitens: Der Zwischenspeicher hält sich hartnäckig. Wenn Sie beim Entwickeln alte Fassungen sehen, ist fast immer das Lager schuld; die Fassungsnummer im Namen (rundgang-v1) ist die Lösung, nicht die Notabschaltung.WarumWie eine Aktualisierung ankommt, ohne dass jemand den Browser leert
Der Zwischenspeicher ist die häufigste Ursache dafür, dass eine Änderung „nicht ankommt“. Das Muster, das trägt, hat drei Teile:
Ein Name mit Fassungsnummer. rundgang-v1, rundgang-v2. Beim Aktivieren löscht der Service Worker alle Lager, die nicht den aktuellen Namen tragen — das steht im Beispiel bereits drin.
Netz zuerst, Lager als Rückfall. Die Fassung im Kurs versucht immer zuerst das Netz und legt die Antwort ins Lager. Damit ist die Anzeige aktuell, solange Netz da ist, und funktioniert ohne. Der umgekehrte Weg — Lager zuerst — ist schneller und liefert deshalb zuverlässig alte Inhalte aus.
Ein Hinweis, wenn eine neue Fassung bereitliegt. Der Service Worker meldet das über ein Ereignis. Eine kleine Leiste „Neue Fassung verfügbar — neu laden“ ist ehrlicher als ein erzwungener Neustart mitten in einer Eingabe.
TiefeWarum der Service Worker nur GET-Anfragen behandeln darf
Ein Service Worker sieht jede Anfrage der Seite, auch das Absenden eines Formulars. Wer alles gleich behandelt, legt irgendwann die Antwort auf ein POST ins Lager — und liefert sie später aus, ohne dass der Vorgang stattgefunden hat.
In einer Bestellstrecke heißt das: eine Bestätigung ohne Bestellung. Der Fehler ist selten, schwer zu finden und teuer, weil er das Vertrauen in die Anzeige zerstört. Deshalb die eine Zeile ganz oben im Beispiel — sie ist die wichtigste der ganzen Datei.