IndexedDB vs localStorage: quale storage del browser usare
IndexedDB vs localStorage
IndexedDB vs localStorage: limiti, velocità, quando usarli | We.Inc
IndexedDB e localStorage a confronto: limiti per browser, sincrono o asincrono, cosa può salvare ciascuno, più una demo dal vivo che scrive la stessa nota in entrambi.
Scegli localStorage per poche impostazioni piccole: salva solo stringhe, circa 5 MiB per origine, e ogni chiamata blocca la pagina finché non termina. Scegli IndexedDB per dati veri: è asincrono, transazionale, salva oggetti, date e file, e la sua quota è una parte del disco. La demo qui sotto scrive la stessa nota in entrambi.
La versione breve
Domanda
localStorage
IndexedDB
Cosa può contenere?
Solo stringhe
Tutto ciò che l'algoritmo structured clone copia, compresi Blob e File
Dimensione
Fino a 5 MiB per origine
Una parte del disco libero, decisa da ogni browser
Blocca la pagina?
Sì, ogni chiamata è sincrona
No, i risultati arrivano tramite eventi o promise
Transazioni e indici
No
Sì
Utilizzabile in un Web Worker
No, è una proprietà di window
Sì
Ideale per
Tema, ultima scheda, una bozza di testo
Dati offline, cache, file, tutto ciò che interroghi
Entrambe le API conservano dati nel browser del visitatore anche dopo la chiusura della scheda, ed entrambe sono limitate all'origine della pagina. La differenza è il peso. localStorage è una piccola mappa sincrona di stringhe che impari in un minuto; IndexedDB è un piccolo database con versioni, object store e transazioni. Questa pagina mostra i limiti reali presi dalla documentazione e ti fa vedere cosa restituisce ciascuna.
Scrivi una nota e premi Salva in entrambi. La pagina la scrive in localStorage come testo JSON e in un object store di IndexedDB come oggetto vero.
Premi Rileggi. Il pannello dei risultati mostra il tipo restituito da ogni API: una stringa da localStorage, un oggetto con una Date funzionante da IndexedDB.
Premi Controlla quota per chiedere a navigator.storage.estimate() quanto spazio usa e può usare questa origine. I numeri sono stime.
Premi Cancella dati demo per rimuovere la chiave della demo ed eliminare il database della demo. Nulla lascia il tuo dispositivo.
Racchiudi localStorage.setItem in un try...catch. Uno storage pieno genera QuotaExceededError, e alcune impostazioni di privacy generano SecurityError al primo accesso.
Salva in localStorage l'output di JSON.stringify e fai il parse in lettura. Le date tornano come stringhe, quindi convertile tu.
Per IndexedDB, un piccolo wrapper come idb o Dexie trasforma lo stile a richieste ed eventi in promise e ti risparmia molto codice ripetitivo.
Chiama navigator.storage.persist() solo per dati che la persona sarebbe dispiaciuta di perdere, come documenti offline. Altrimenti il browser può eliminarli quando lo spazio scarseggia.
Non tenere mai segreti o token di sessione in nessuno dei due storage. Qualsiasi script in esecuzione sulla pagina può leggerli.
Domande frequenti
Quanto può contenere localStorage?
MDN documenta un limite di 5 MiB di local storage e 5 MiB di session storage per origine, 10 MiB in totale. Poiché i valori sono stringhe UTF-16, il numero di caratteri che ci stanno può essere inferiore a quanto pensi. Superare il limite genera un QuotaExceededError.
Quanto può contenere IndexedDB?
Dipende dal browser e dal disco. I browser Chromium concedono a un'origine fino al 60% della dimensione totale del disco. Firefox concede il valore minore tra il 10% del disco e 10 GiB per gruppo di siti in modalità best-effort. Le app browser Safari concedono circa il 60% del disco. Usa navigator.storage.estimate() per leggere il valore reale.
IndexedDB è più veloce di localStorage?
Per un singolo valore piccolo, localStorage di solito è più rapido da scrivere nel codice e abbastanza veloce in esecuzione. Il problema è che è sincrono, quindi letture e scritture grandi bloccano il main thread. IndexedDB lavora fuori dal flusso principale e ti avvisa quando ha finito, così lo scorrimento e la digitazione restano fluidi.
Il browser può cancellare i miei dati IndexedDB?
Sì. Per impostazione predefinita lo storage è best-effort, quindi il browser può eliminare i dati di un'origine quando il disco è sotto pressione. Chiedere navigator.storage.persist() passa alla modalità persistente, in cui solo la persona può cancellarli. Firefox mostra una richiesta di permesso; Chrome e Safari decidono in base a come la persona usa il sito.
Dovrei usare localStorage per un token di login?
No. Qualsiasi script sulla pagina, compreso uno iniettato, può leggere localStorage e IndexedDB. Tieni gli identificatori di sessione in cookie contrassegnati HttpOnly, Secure e SameSite, che gli script della pagina non possono leggere.
Perché conta che sia sincrono
Quando il codice chiama localStorage.getItem, il browser smette di eseguire altro JavaScript finché il valore non torna dal disco. Per il nome di un tema nessuno se ne accorge. Per qualche megabyte di JSON analizzato a ogni caricamento, si nota come una pausa prima che la pagina risponda ai tocchi.
IndexedDB restituisce subito un oggetto request e lancia success o error più tardi. Questa forma richiede più codice, ed è per questo che la maggior parte dei progetti usa un wrapper a promise, ma non tiene mai in ostaggio la pagina.
Stringhe contro structured clone
localStorage trasforma tutto in testo. Salvi il numero 3 e rileggi la stringa "3"; salvi un oggetto senza JSON.stringify e rileggi "[object Object]".
IndexedDB copia i valori con l'algoritmo structured clone, quindi una Date resta una Date, una Map resta una Map, e un Blob o un File può essere salvato così com'è. È questo che lo rende adatto a immagini offline, audio registrato o bozze con allegati.
Una regola semplice per scegliere
Se i dati stanno in una riga breve e li leggi una volta all'avvio, localStorage va bene. Se vorresti cercarli, contarli, sfogliarli a pagine, salvarci file binari o aggiornarli da un service worker, usa IndexedDB.
I dati sul server sono una terza opzione che spesso batte entrambe: se la persona si aspetta di vedere la stessa cosa su un altro dispositivo, quei dati vanno nel tuo database, con lo storage del browser solo come cache.
Limiti di storage per browser
Valori come documentati nella pagina di MDN sulle quote di storage. IndexedDB, la Cache API e l'origin private file system condividono la stessa quota.
Quota per origine
Browser
localStorage
IndexedDB (best-effort)
IndexedDB (persistente)
Chrome, Edge e altri Chromium
5 MiB
Fino al 60% del disco totale
Fino al 60% del disco totale
Firefox
5 MiB
Il minore tra 10% del disco e 10 GiB per gruppo di siti
Fino al 50% del disco, con tetto a 8 TiB
App browser Safari
5 MiB
Circa il 60% del disco totale
Circa il 60% del disco totale
App che incorporano contenuti web (WebKit)
5 MiB
Circa il 15% del disco totale
Circa il 15% del disco totale
Lo stesso salvataggio con entrambe le API
localStorage: stringify, protezione, parse
Il try...catch gestisce uno storage pieno o bloccato. La data va ricostruita a mano dopo il parse.
IndexedDB: apri, aggiorna, scrivi in una transazione
onupgradeneeded viene eseguito la prima volta e ogni volta che il numero di versione sale; è l'unico punto in cui creare gli object store.
Chiedi quanto spazio hai, e chiedi di tenerlo
estimate() restituisce conteggi di byte approssimativi. persist() si risolve in true se il browser ha concesso lo storage persistente.
Salva una nota in entrambi gli storage
Questa demo gira solo nel tuo browser. Scrive sotto la chiave we-demo-note e in un database chiamato we-demo-db, e il pulsante Cancella li rimuove entrambi.
Nota da salvare
Chiamare il tipografo venerdì
Salva in entrambi
Rileggi
Controlla quota
Cancella dati demo
Ancora nulla letto. Salva una nota, poi premi Rileggi.
localStorage ha restituito
IndexedDB ha restituito
Tipo: {v}
savedAt è una Date: {v}
Nulla salvato
Nota salvata in localStorage e IndexedDB.
Chiave e database della demo rimossi.
Questa origine usa circa {n} MB su circa {v} MB disponibili.
Questo browser non offre navigator.storage.estimate().
Lo storage non ha funzionato in questo browser: {v}