PWA Offline-First

Arquitectura de aplicación web progresiva con caché de service worker, almacenamiento IndexedDB, sincronización en segundo plano y resolución de conflictos para operaciones de campo sin conectividad.

Última actualización: 2025-02-18

Arquitectura PWA Offline-First

Certexi es una Aplicación Web Progresiva completamente capaz de operar offline. Las operaciones aduaneras continúan sin interrupciones sin conectividad a internet — los eventos se encolan localmente y se sincronizan automáticamente cuando se restaura la conexión.

Arquitectura

Loading diagram…

Indicador de Estado Offline

<div className="flex flex-col gap-3 w-72">
  <Card>
    <CardContent className="p-3 flex items-center gap-3">
      <div className="w-2.5 h-2.5 rounded-full bg-green-500 animate-pulse" />
      <div className="flex-1">
        <div className="text-sm font-medium">En línea</div>
        <div className="text-xs text-muted-foreground">Todos los sistemas conectados</div>
      </div>
      <Badge variant="outline" className="text-green-500">Sincronizado</Badge>
    </CardContent>
  </Card>
  <Card>
    <CardContent className="p-3 flex items-center gap-3">
      <div className="w-2.5 h-2.5 rounded-full bg-amber-500" />
      <div className="flex-1">
        <div className="text-sm font-medium">Sin conexión</div>
        <div className="text-xs text-muted-foreground">3 eventos en cola</div>
      </div>
      <Badge variant="outline" className="text-amber-500">Pendiente</Badge>
    </CardContent>
  </Card>
  <Card>
    <CardContent className="p-3 space-y-2">
      <div className="flex items-center justify-between text-xs">
        <span className="text-muted-foreground">Cola de sincronización</span>
        <span>3 / 3 eventos</span>
      </div>
      <Progress value={0} className="h-1.5" />
      <Button size="sm" variant="outline" className="w-full text-xs">Forzar Sincronización</Button>
    </CardContent>
  </Card>
</div>

Componentes Principales

Service Worker (/public/sw.js)

El service worker gestiona toda la caché y sincronización en segundo plano:

  • Cachea activos estáticos (HTML, CSS, JS, imágenes, fuentes)
  • Implementa estrategias de red primero y caché primero
  • Maneja la sincronización en segundo plano para eventos encolados
  • Proporciona páginas de respaldo offline para rutas no coincidentes

Almacenamiento IndexedDB (/lib/offline/storage.ts)

Tres almacenes de objetos impulsan la experiencia offline:

AlmacénPropósitoClave
eventsOperaciones encoladas esperando sincronizaciónID auto-generado
unitsUnidades de transporte cacheadas para acceso offlineID de Unidad
responsesRespuestas de API cacheadas con TTLURL de Solicitud

Indicador Offline (/components/offline-indicator.tsx)

Retroalimentación visual para los usuarios que muestra el estado en línea/offline en tiempo real, conteo de sincronización pendiente y activador de sincronización manual.

Flujo de Trabajo Offline Completo

Los usuarios pueden realizar todas las operaciones críticas mientras están offline:

  • Escanear tags NFC y códigos QR
  • Capturar fotos y ubicación GPS
  • Registrar observaciones de inspección
  • Ver unidades de transporte cacheadas
  • Progresar a través de todas las etapas del flujo de trabajo

Los eventos se encolan en IndexedDB con la siguiente estructura:

interface QueuedEvent {
  id: string;               // "offline-{timestamp}-{random}"
  eventType: string;        // inspection, entry, exit, scale, etc.
  data: any;                // Full event payload
  timestamp: number;        // When queued (ms)
  retries: number;          // Sync retry count
  synced: boolean;          // Sync status
}

Estrategias de Caché

Activos Estáticos (Caché Primero)

HTML, CSS, JavaScript, imágenes y fuentes se cachean indefinidamente y se actualizan cuando cambia la versión del service worker.

Solicitudes de API (Red Primero)

Las llamadas a API siempre intentan la red primero, recurriendo a respuestas cacheadas cuando está offline. Las respuestas se cachean por 5 minutos (configurable).

Páginas (Red Primero)

El contenido dinámico siempre está fresco cuando hay conexión. Las páginas cacheadas están disponibles offline con una página de respaldo para rutas no coincidentes.

Sincronización en Segundo Plano

Cuando se restaura la conexión:

  1. El service worker activa la sincronización en segundo plano
  2. Los eventos encolados se procesan secuencialmente
  3. Cada evento se envía a su endpoint apropiado
  4. Los eventos fallidos se reintentan con backoff exponencial (máximo 5 reintentos)
  5. Los eventos sincronizados exitosamente se eliminan de la cola
ℹ️

Soporte de Navegador

La Background Sync API es compatible con Chrome 49+ y Edge 79+. Para Safari y Firefox, Certexi recurre a sincronización manual en el evento online.

Mapeo de Endpoints de Sincronización

Tipo de EventoEndpoint
inspection/api/uma/attestation
entry/api/workflow/entry
exit/api/workflow/exit
scale/api/workflow/scale
Default/api/events

Integridad de Datos

Las operaciones offline están protegidas por múltiples capas:

  • Hashing criptográfico para todos los eventos
  • Verificación de árbol Merkle en la sincronización
  • Prevención de ataques de repetición basada en timestamp
  • Detección de duplicados del lado del servidor
⚠️

Re-autenticación

Después de un período offline extendido, los usuarios pueden necesitar re-autenticarse. Las operaciones offline usan credenciales cacheadas que expiran según el tiempo de vida del token JWT.

Configuración

Versión de Caché

Incremente CACHE_VERSION en /public/sw.js para forzar una actualización completa de caché en la próxima visita.

TTL de Caché

Caché de respuesta de API predeterminada: 5 minutos (300,000ms). Configurable por solicitud.

Límite de Reintentos

Máximo 5 reintentos de sincronización antes de descartar un evento. Los eventos fallidos se registran para recuperación manual.

Soporte de Navegadores

CaracterísticaChromeFirefoxSafariEdge
Service Worker40+44+11.1+17+
IndexedDB24+16+10+12+
Background Sync49+FlagNo79+
Cache API40+41+11.1+17+

Relacionado