IndexedDB vs localStorage : quel stockage navigateur utiliser
IndexedDB vs localStorage
IndexedDB vs localStorage : limites, vitesse, quand l'utiliser | We.Inc
Comparez IndexedDB et localStorage côte à côte : limites de taille par navigateur, synchrone ou asynchrone, ce que chacun peut stocker, plus une démo en direct qui enregistre une note dans les deux.
Choisissez localStorage pour quelques petits réglages : il ne stocke que des chaînes, environ 5 MiB par origine, et chaque appel bloque la page jusqu'à la fin. Choisissez IndexedDB pour de vraies données : il est asynchrone, transactionnel, stocke des objets, des dates et des fichiers, et son quota est une part du disque. La démo ci-dessous écrit une note dans les deux.
La version courte
Question
localStorage
IndexedDB
Que peut-il contenir ?
Des chaînes uniquement
Tout ce que l'algorithme de clonage structuré copie, y compris Blob et File
Taille
Jusqu'à 5 MiB par origine
Une part du disque libre, fixée par chaque navigateur
Bloque-t-il la page ?
Oui, chaque appel est synchrone
Non, les résultats arrivent par événements ou promesses
Transactions et index
Non
Oui
Utilisable dans un Web Worker
Non, c'est une propriété de window
Oui
Idéal pour
Thème, dernier onglet, une chaîne de brouillon
Données hors ligne, caches, fichiers, tout ce que vous interrogez
Les deux API conservent des données dans le navigateur du visiteur après la fermeture de l'onglet, et toutes deux sont limitées à l'origine de la page. La différence tient au poids. localStorage est une minuscule table de chaînes synchrone qu'on apprend en une minute ; IndexedDB est une petite base de données avec des versions, des object stores et des transactions. Cette page présente les vraies limites tirées de la documentation et vous laisse voir ce que chacune renvoie.
Tapez une note et appuyez sur Enregistrer dans les deux. La page l'écrit dans localStorage en texte JSON et dans un object store IndexedDB sous forme de véritable objet.
Appuyez sur Relire. Le panneau de résultat montre le type renvoyé par chaque API : une chaîne depuis localStorage, un objet avec une Date fonctionnelle depuis IndexedDB.
Appuyez sur Vérifier le quota pour demander à navigator.storage.estimate() combien cette origine utilise et peut utiliser. Les chiffres sont des estimations.
Appuyez sur Effacer les données de démo pour supprimer la clé de démo et la base de démo. Rien ne quitte votre appareil.
Entourez localStorage.setItem d'un try...catch. Un stockage plein lève une QuotaExceededError, et certains réglages de confidentialité lèvent une SecurityError au premier accès.
Stockez la sortie de JSON.stringify dans localStorage et parsez-la à la lecture. Les dates reviennent sous forme de chaînes, convertissez-les vous-même.
Pour IndexedDB, une petite surcouche comme idb ou Dexie transforme le style requêtes et événements en promesses et vous épargne beaucoup de code répétitif.
N'appelez navigator.storage.persist() que pour des données que la personne serait contrariée de perdre, comme des documents hors ligne. Sinon, le navigateur peut les évincer quand l'espace manque.
Ne gardez jamais de secrets ni de jetons de session dans l'un ou l'autre. N'importe quel script exécuté sur la page peut les lire.
Questions fréquentes
Combien localStorage peut-il contenir ?
MDN documente une limite de 5 MiB de local storage et 5 MiB de session storage par origine, soit 10 MiB au total. Comme les valeurs sont des chaînes UTF-16, le nombre de caractères que vous pouvez y mettre peut être plus faible que prévu. Dépasser la limite lève une QuotaExceededError.
Combien IndexedDB peut-il contenir ?
Cela dépend du navigateur et du disque. Les navigateurs Chromium autorisent une origine jusqu'à 60% de la taille totale du disque. Firefox autorise le plus petit entre 10% du disque et 10 GiB par groupe de sites en mode best-effort. L'app navigateur Safari autorise environ 60% du disque. Utilisez navigator.storage.estimate() pour lire le chiffre réel.
IndexedDB est-il plus rapide que localStorage ?
Pour une seule petite valeur, localStorage est généralement plus rapide à écrire dans le code et assez rapide à l'exécution. Le problème est qu'il est synchrone, donc les grosses lectures et écritures figent le thread principal. IndexedDB fait le travail en dehors du flux principal et vous prévient quand il a fini, ce qui garde le défilement et la saisie fluides.
Le navigateur peut-il supprimer mes données IndexedDB ?
Oui. Le stockage est en best-effort par défaut, donc le navigateur peut évincer les données d'une origine quand le disque manque de place. Appeler navigator.storage.persist() passe en mode persistant, où seule la personne peut les effacer. Firefox affiche une demande d'autorisation ; Chrome et Safari décident selon la façon dont la personne utilise le site.
Dois-je utiliser localStorage pour un jeton de connexion ?
Non. N'importe quel script de la page, y compris un script injecté, peut lire localStorage et IndexedDB. Gardez les identifiants de session dans des cookies marqués HttpOnly, Secure et SameSite, que les scripts de la page ne peuvent pas lire.
Pourquoi le synchrone compte
Quand le code appelle localStorage.getItem, le navigateur arrête d'exécuter tout autre JavaScript jusqu'à ce que la valeur revienne du disque. Pour un nom de thème, personne ne le remarque. Pour quelques mégaoctets de JSON parsés à chaque chargement de page, cela se traduit par une pause avant que la page ne réagisse aux appuis.
IndexedDB renvoie immédiatement un objet de requête et déclenche success ou error plus tard. Cette forme demande plus de code, c'est pourquoi la plupart des projets utilisent une surcouche à promesses, mais elle ne prend jamais la page en otage.
Chaînes contre clonage structuré
localStorage transforme tout en texte. Stockez le nombre 3 et vous relisez la chaîne "3" ; stockez un objet sans JSON.stringify et vous relisez "[object Object]".
IndexedDB copie les valeurs avec l'algorithme de clonage structuré, donc une Date reste une Date, une Map reste une Map, et un Blob ou un File peut être enregistré tel quel. C'est ce qui le rend adapté aux images hors ligne, à l'audio enregistré ou aux brouillons avec pièces jointes.
Une règle simple pour choisir
Si les données tiennent sur une courte ligne et que vous les lisez une fois au démarrage, localStorage convient. Si vous voulez les rechercher, les compter, les paginer, y stocker des fichiers binaires ou les mettre à jour depuis un service worker, utilisez IndexedDB.
Les données serveur sont une troisième option qui bat souvent les deux : si la personne s'attend à voir la même chose sur un autre appareil, elles ont leur place dans votre base de données, avec le stockage navigateur uniquement comme cache.
Limites de stockage par navigateur
Chiffres tels que documentés sur la page de MDN consacrée aux quotas de stockage. IndexedDB, la Cache API et l'origin private file system partagent le même quota.
Quota par origine
Navigateur
localStorage
IndexedDB (best-effort)
IndexedDB (persistant)
Chrome, Edge et autres Chromium
5 MiB
Jusqu'à 60% du disque total
Jusqu'à 60% du disque total
Firefox
5 MiB
Le plus petit entre 10% du disque et 10 GiB par groupe de sites
Jusqu'à 50% du disque, plafonné à 8 TiB
App navigateur Safari
5 MiB
Environ 60% du disque total
Environ 60% du disque total
Apps qui intègrent du contenu web (WebKit)
5 MiB
Environ 15% du disque total
Environ 15% du disque total
Le même enregistrement dans les deux API
localStorage : stringify, protection, parse
Le try...catch gère un stockage plein ou bloqué. La date doit être reconstruite à la main après le parse.
IndexedDB : ouvrir, mettre à niveau, écrire dans une transaction
onupgradeneeded s'exécute la première fois et chaque fois que le numéro de version augmente ; c'est le seul endroit où créer des object stores.
Demander l'espace disponible, et demander à le garder
estimate() renvoie des nombres d'octets approximatifs. persist() se résout à true si le navigateur a accordé le stockage persistant.
Enregistrer une note dans les deux stockages
Cette démo s'exécute uniquement dans votre navigateur. Elle écrit sous la clé we-demo-note et dans une base appelée we-demo-db, et le bouton Effacer supprime les deux.
Note à enregistrer
Appeler l'imprimeur vendredi
Enregistrer dans les deux
Relire
Vérifier le quota
Effacer les données de démo
Rien n'a encore été lu. Enregistrez une note, puis appuyez sur Relire.
localStorage a renvoyé
IndexedDB a renvoyé
Type : {v}
savedAt est une Date : {v}
Rien n'est stocké
Note enregistrée dans localStorage et IndexedDB.
Clé et base de démo supprimées.
Cette origine utilise environ {n} MB sur environ {v} MB disponibles.
Ce navigateur ne propose pas navigator.storage.estimate().