Офлайн-режим и синхронизация

↑ 8.4 Frontend System Design · ← Предыдущая · → Следующая

Желательно~3 мин чтенияУровень: senior

Зачем это на собесе

Offline-first — сложный кейс; проверяют умение обеспечить консистентность.

Уровни поддержки

  1. Оболочка offline: Service Worker кэширует статику, приложение открывается.
  2. Чтение offline: данные в IndexedDB/кэше.
  3. Запись offline: очередь мутаций, отправка после восстановления сети.
  4. Полная синхронизация: несколько устройств, разрешение конфликтов.

Хранилища

ХранилищеОсобенности
localStorageсинхронный, ~5 МБ, строки
IndexedDBасинхронное, большие объёмы, индексы (Dexie, idb)
Cache APIответы HTTP (Service Worker)
OPFSфайловая система, большие файлы

Очередь мутаций

type Mutation = { id: string; type: string; payload: unknown; createdAt: number; attempts: number }
 
async function enqueue(m: Mutation) { await db.outbox.put(m); tryFlush() }
 
async function tryFlush() {
  if (!navigator.onLine) return
  for (const m of await db.outbox.orderBy('createdAt').toArray()) {
    try { await api.apply(m); await db.outbox.delete(m.id) }
    catch (e) { if (isFatal(e)) await markFailed(m); break }
  }
}
window.addEventListener('online', tryFlush)

Требования: идемпотентность (ключ идемпотентности), сохранение порядка, ограничение повторов, показ статуса пользователю.

Конфликты

СтратегияОписание
Last write winsпобеждает последняя запись; просто, возможна потеря
По версии (ETag, version)сервер отвергает устаревшую, клиент сливает
Слияние по полямконфликтуют только одинаковые поля
CRDT / OTавтоматическое слияние (коллаборативное редактирование)
Ручное разрешениепоказать пользователю

Синхронизация

  • pull по updatedSince / cursor, push очереди;
  • фоновая синхронизация (Background Sync API, периодически);
  • дельты вместо полной загрузки;
  • миграции схемы IndexedDB;
  • navigator.onLine не гарантирует наличие сети: проверять реальным запросом.

UX

Индикатор состояния (offline, синхронизация, ошибка), понятные сообщения, безопасное поведение при истечении токена.

Вопросы с ответами