Sofortantwort
Progressive Web App einfach erklärt
Web-App mit nativen App-Funktionen: offline, installierbar, Push-Benachrichtigungen.
- Kurz gesagt
- Installierbar: Nutzer können die App auf dem Homescreen speichern
- Typischer Einsatz
- KI-Tools ohne App Store, Offline-First-Anwendungen, Push-Benachrichtigungen
- Wichtig zu wissen
- Kein App Store nötig: Direkt über den Browser installierbar
Progressive Web App im Überblick
Native Apps (iOS/Android) haben Vorteile: Sie funktionieren offline, können auf dem Homescreen installiert werden und senden Push-Benachrichtigungen. Aber sie brauchen einen App Store, Review-Prozesse und separate Codebases für iOS und Android.
PWAs bringen diese Funktionen ins Web: Eine einzige Codebase, kein App Store, sofortige Updates. Der Nutzer besucht die Website, bekommt einen „Installieren”-Dialog und hat danach eine App-ähnliche Erfahrung – vollbild, ohne Browser-Chrome, mit eigenem App-Icon.
PWA vs. Native App:
| Aspekt | Native App | PWA |
|---|---|---|
| Installation | App Store | Browser-Dialog |
| Updates | App Store Review | Sofort |
| Offline | ✅ | ✅ (mit Service Worker) |
| Push-Benachrichtigungen | ✅ | ✅ (eingeschränkt auf iOS) |
| Hardware-Zugriff | Vollständig | Eingeschränkt |
| Codebase | iOS + Android | Eine für alle |
| Auffindbarkeit | App Store | Google-Suche |
iOS vs. Android – wichtige Unterschiede
PWA-Support ist auf Android deutlich besser als auf iOS:
| Feature | Android (Chrome) | iOS (Safari) |
|---|---|---|
| Installation | ✅ Vollständig | ✅ Seit iOS 16.4 |
| Push-Benachrichtigungen | ✅ | ✅ Seit iOS 16.4 |
| Background Sync | ✅ | ❌ |
| Bluetooth/NFC | ✅ | ❌ |
| Persistent Storage | ✅ | Begrenzt |
Technisch betrachtet
Web App Manifest
{
"name": "KI-Assistent",
"short_name": "Grundlagen",
"start_url": "/",
"display": "standalone",
"background_color": "#0f172a",
"theme_color": "#6366f1",
"icons": [
{ "src": "/icon-192.png", "sizes": "192x192", "type": "image/png" },
{ "src": "/icon-512.png", "sizes": "512x512", "type": "image/png" },
{ "src": "/icon-512-maskable.png", "sizes": "512x512", "type": "image/png", "purpose": "maskable" }
],
"screenshots": [
{ "src": "/screenshot-mobile.png", "sizes": "390x844", "type": "image/png", "form_factor": "narrow" }
]
}
Service Worker – Caching-Strategien
Workbox bietet verschiedene Strategien je nach Ressourcentyp:
import { registerRoute } from 'workbox-routing';
import { CacheFirst, NetworkFirst, StaleWhileRevalidate } from 'workbox-strategies';
// Statische Assets: Cache First (lange Gültigkeit)
registerRoute(
({ request }) => request.destination === 'image',
new CacheFirst({ cacheName: 'images', plugins: [
new ExpirationPlugin({ maxAgeSeconds: 30 * 24 * 60 * 60 }) // 30 Tage
]})
);
// API-Calls: Network First (immer aktuell, Fallback auf Cache)
registerRoute(
({ url }) => url.pathname.startsWith('/api/'),
new NetworkFirst({ cacheName: 'api-cache' })
);
// HTML-Seiten: Stale While Revalidate (schnell + aktuell)
registerRoute(
({ request }) => request.mode === 'navigate',
new StaleWhileRevalidate({ cacheName: 'pages' })
);
Push-Benachrichtigungen implementieren
// 1. Berechtigung anfragen
const permission = await Notification.requestPermission();
// 2. Service Worker registrieren und Push-Subscription erstellen
const registration = await navigator.serviceWorker.ready;
const subscription = await registration.pushManager.subscribe({
userVisibleOnly: true,
applicationServerKey: urlBase64ToUint8Array(PUBLIC_VAPID_KEY),
});
// 3. Subscription an Server senden
await fetch('/api/push/subscribe', {
method: 'POST',
body: JSON.stringify(subscription),
headers: { 'Content-Type': 'application/json' },
});
// 4. Im Service Worker: Push empfangen
self.addEventListener('push', (event) => {
const data = event.data.json();
event.waitUntil(
self.registration.showNotification(data.title, {
body: data.body,
icon: '/icon-192.png',
})
);
});
PWA-Checkliste (Lighthouse-Kriterien)
- ✅ HTTPS (Pflicht für Service Worker)
- ✅ Web App Manifest mit allen Pflichtfeldern
- ✅ Service Worker registriert
- ✅ Icons in 192px und 512px
- ✅
start_urlim Manifest - ✅
display: standaloneoderfullscreen - ✅ Offline-Fallback-Seite
- ✅
theme_colorgesetzt