IndexedDB en pratique : stockage de fichiers volumineux et architecture hors ligne dans le navigateur
Pourquoi IndexedDB ?
Les options de stockage du navigateur ont chacune des limites claires :
| Option | Capacité | Types de données | API synchrone | Cas d'usage |
|---|---|---|---|---|
| Cookie | ~4KB | Chaîne | ✅ | Identifiants de session |
| localStorage | ~5MB | Chaîne | ✅ | Paramètres simples |
| sessionStorage | ~5MB | Chaîne | ✅ | État temporaire |
| IndexedDB | Des centaines de Mo–Go | Toutes données structurées | ❌ Async | Fichiers volumineux, apps hors ligne |
Pour les sites d'outils qui doivent mettre en cache dans le navigateur les intermédiaires de traitement PDF, les modules WASM ou l'historique des téléversements des utilisateurs, IndexedDB est le seul choix viable.
Concepts centraux
Base de données → Object Store → Enregistrement
Database: "toolsku-cache"
├── ObjectStore: "wasm-modules" (key: moduleName)
├── ObjectStore: "file-cache" (key: fileHash, index: timestamp)
└── ObjectStore: "user-preferences" (key: settingKey)
Transactions et concurrence
Les transactions IndexedDB sont auto-validées, et une seule transaction de lecture/écriture par Object Store est autorisée à la fois :
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 dans ToolsKu
Cache de modules WASM
ffmpeg.wasm fait environ 30 Mo et prend de 3 à 5 secondes à charger à chaque fois. Après la mise en cache dans IndexedDB, les visites suivantes sont quasi instantanées :
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;
}
Stockage fragmenté pour les fichiers volumineux
Stocker des fichiers de plus de 50 Mo dans IndexedDB en une seule fois n'est pas idéal. Une stratégie de fragmentage :
File (200MB) → split into 4MB chunks → store each in IndexedDB
key: "file:{hash}:chunk:{index}"
Read in order and concatenate → restore full file
Migration de version
Lorsque le schéma de la base de données change, la migration est gérée dans 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' });
}
};
Bonne pratique : ajoutez uniquement des ObjectStores — ne les supprimez jamais. Incrémentez le numéro de version pour déclencher la migration et évitez de supprimer les données utilisateur.
IndexedDB vs OPFS
| Caractéristique | IndexedDB | OPFS (Origin Private File System) |
|---|---|---|
| Maturité de l'API | Large prise en charge | Chrome 86+ / Safari 15.2+ |
| Modèle de lecture/écriture | Magasin clé-valeur | Véritable système de fichiers |
| Performances | Modérées | Plus élevées (accès synchrone surtout) |
| Idéal pour | Cache structuré | E/S de fichiers volumineux |
ToolsKu utilise principalement IndexedDB, avec OPFS comme optimisation des performances sur Chrome.
Résumé
IndexedDB est une infrastructure essentielle pour les outils de navigateur offline-first. Une bonne conception d'Object Stores, le cache WASM et les stratégies de stockage fragmenté permettent à ToolsKu de rester réactif même sur les réseaux lents.
Essayez ces outils exécutés localement dans le navigateur — aucune inscription requise →