IndexedDB en la práctica: almacenamiento de archivos grandes y arquitectura offline en el navegador

技术架构

¿Por qué IndexedDB?

Las opciones de almacenamiento del navegador tienen límites claros cada una:

Opción Capacidad Tipos de datos API síncrona Caso de uso
Cookie ~4KB String Identificadores de sesión
localStorage ~5MB String Configuraciones simples
sessionStorage ~5MB String Estado temporal
IndexedDB Cientos de MB–GB Cualquier dato estructurado ❌ Async Archivos grandes, apps offline

Para sitios de herramientas que necesitan guardar en el navegador intermedios de procesamiento de PDF, módulos WASM o el historial de cargas de los usuarios, IndexedDB es la única opción viable.


Conceptos centrales

Base de datos → Object Store → Registro

Database: "toolsku-cache"
  ├── ObjectStore: "wasm-modules"     (key: moduleName)
  ├── ObjectStore: "file-cache"       (key: fileHash, index: timestamp)
  └── ObjectStore: "user-preferences" (key: settingKey)

Transacciones y concurrencia

Las transacciones de IndexedDB se auto-confirman, y solo se permite una transacción de lectura/escritura por Object Store a la vez:

const tx = db.transaction(['file-cache'], 'readwrite');
const store = tx.objectStore('file-cache');
await store.put({ hash: 'abc123', data: arrayBuffer, timestamp: Date.now() });
await tx.done; // Wait for transaction to complete

IndexedDB en ToolsKu

Caché de módulos WASM

ffmpeg.wasm tiene unos 30 MB y tarda de 3 a 5 segundos en cargar cada vez. Tras guardarlo en caché en IndexedDB, las visitas siguientes son casi instantáneas:

async function getWasmModule(name: string): Promise<ArrayBuffer> {
  const cached = await idb.get('wasm-modules', name);
  if (cached) return cached;

  const response = await fetch(`/wasm/${name}.wasm`);
  const buffer = await response.arrayBuffer();
  await idb.put('wasm-modules', buffer, name);
  return buffer;
}

Almacenamiento en fragmentos para archivos grandes

Guardar archivos de más de 50 MB en IndexedDB de una sola vez no es ideal. Una estrategia de fragmentación:

File (200MB) → split into 4MB chunks → store each in IndexedDB
key: "file:{hash}:chunk:{index}"
Read in order and concatenate → restore full file

Migración de versiones

Cuando cambia el esquema de la base de datos, la migración se maneja en onupgradeneeded:

const request = indexedDB.open('toolsku-cache', 2); // version 2

request.onupgradeneeded = (event) => {
  const db = event.target.result;
  if (event.oldVersion < 2) {
    db.createObjectStore('processing-history', { keyPath: 'id' });
  }
};

Práctica recomendada: agrega ObjectStores únicamente — nunca los elimines. Incrementa el número de versión para activar la migración y evita borrar los datos de los usuarios.


IndexedDB vs OPFS

Característica IndexedDB OPFS (Origin Private File System)
Madurez de API Amplio soporte Chrome 86+ / Safari 15.2+
Modelo de lectura/escritura Almacén clave-valor Sistema de archivos real
Rendimiento Moderado Mayor (especialmente acceso síncrono)
Mejor para Caché estructurado E/S de archivos grandes

ToolsKu usa principalmente IndexedDB, con OPFS como optimización de rendimiento en Chrome.


Resumen

IndexedDB es infraestructura esencial para herramientas de navegador offline-first. Un buen diseño de ObjectStores, el caché de WASM y las estrategias de almacenamiento en fragmentos permiten que ToolsKu siga respondiendo incluso en redes lentas.

Prueba estas herramientas que se ejecutan en tu navegador — no requieren registro →

#IndexedDB#浏览器存储#离线#大文件#架构