Warum Offline-First?
Mobiler Nutzer erwarten, dass Apps überall funktionieren — auch unterirdisch, in ländlichen Gebieten oder auf Flügen. Eine Offline-First-Architektur stellt sicher, dass die App auch bei Verlust der Verbindung sanft abstürzt.
Architekturbestandteile
1. Lokale Datenbank
Wir verwenden Realm für die lokale Speicherung, da es reaktive Abfragen und eine Unterstützung für Konfliktlösungen bietet.
const realm = await Realm.open({ schema: [TaskSchema, UserSchema] });
// Lokal schreiben — sofort, ohne Netzwerk erforderlich
realm.write(() => {
realm.create("Task", { id: uuid(), title: "Neue Aufgabe", synced: false });
});
// Lokal lesen — sofort, ohne Ladezustände
const tasks = realm.objects("Task").filtered("synced == false");2. Synchronisationsmotor
Ein Hintergrundsynchronisationsmotor schiebt lokale Änderungen auf den Server und zieht remote Änderungen her, wenn die Verbindung wiederhergestellt ist.
class SyncEngine {
async syncPendingChanges() {
const pending = await this.localDb.getUnsynced();
for (const item of pending) {
try {
await this.api.push(item);
await this.localDb.markSynced(item.id);
} catch (error) {
this.queueForRetry(item);
}
}
}
}3. Konfliktlösung
| Strategie | Wann verwenden |
|---|---|
| Letzte Schreiboperation gewinnt | Simple Daten, geringes Konflikt-Risiko |
| Merge | Komplementäre Änderungen an verschiedenen Feldern |
| Manuelle Konfliktlösung | Kritische Daten, Konflikte durch Geschäftslogik |
Testen der Offline-Behavior
- Airplane-Modus-Testen auf echten Geräten
- Netzwerk-Throttling-Simulation
- Testen von Szenarien für Konflikte bei der Synchronisation
- Überprüfung der Datenintegrität nach der Synchronisation