Esistono molte opzioni diverse per archiviare i dati nel browser. Quale è la migliore per le tue esigenze?
Le connessioni a internet possono essere instabili o inesistenti in mobilità, motivo per cui il supporto offline e le prestazioni affidabili sono funzionalità comuni nelle PWA. Anche in ambienti wireless perfetti, l'uso giudizioso della memorizzazione nella cache e di altre tecniche di archiviazione può migliorare notevolmente l'esperienza utente. Esistono diversi modi per memorizzare nella cache le risorse statiche dell'applicazione (HTML, JavaScript, CSS, immagini e così via) e i dati (dati utente, articoli di notizie e così via). Ma qual è la soluzione migliore? Quanto puoi archiviare? Come impedisci che venga eliminato?
Cosa devo usare?
Ecco un consiglio generale per l'archiviazione delle risorse:
- Per le risorse di rete necessarie per caricare l'app, utilizza l'API Cache Storage (parte dei service worker).
- Per i contenuti basati su file, utilizza l'Origin Private File System (OPFS).
- Per altri dati, utilizza IndexedDB (con un wrapper di promesse).
IndexedDB, OPFS e l'API Cache Storage sono supportati in tutti i browser moderni.
Sono asincroni e non bloccano il thread principale (ma esiste anche una variante sincrona di OPFS disponibile esclusivamente nei web worker). Sono accessibili dall'oggetto window, dai web worker e dai service worker, il che consente di utilizzarli ovunque nel codice.
E gli altri meccanismi di archiviazione?
Nel browser sono disponibili diversi altri meccanismi di archiviazione, ma il loro utilizzo è limitato e possono causare problemi di prestazioni significativi.
SessionStorage è specifico per le schede e limitato alla durata della scheda. Può essere utile per archiviare piccole quantità di informazioni specifiche della sessione, ad esempio una chiave IndexedDB. Deve essere utilizzato con cautela perché è sincrono e blocca il thread principale. È limitato a circa 5 MB e può contenere solo stringhe. Poiché è specifico per le schede, non è accessibile da web worker o service worker.
LocalStorage deve essere evitato perché è sincrono e blocca il thread principale. È limitato a circa 5 MB e può contenere solo stringhe. LocalStorage non è accessibile da web worker o service worker.
I cookie hanno i loro utilizzi, ma non devono essere utilizzati per l'archiviazione. I cookie vengono inviati con ogni richiesta HTTP, quindi l'archiviazione di una quantità di dati superiore a una piccola quantità aumenterà notevolmente le dimensioni di ogni richiesta web. Sono sincroni e non sono accessibili dai web worker. Come LocalStorage e SessionStorage, i cookie sono limitati solo alle stringhe.
L'API File System Access è stata progettata per consentire agli utenti di leggere e modificare i file sul file system locale. L'utente deve concedere l'autorizzazione prima che una pagina possa leggere o scrivere in qualsiasi file locale e le autorizzazioni non vengono mantenute tra le sessioni, a meno che un handle di file non venga memorizzato nella cache in IndexedDB. L'API File System Access è più adatta a casi d'uso come gli editor, in cui devi aprire un file, modificarlo e poi, se necessario, salvare nuovamente le modifiche nel file.
L'API File System e l'API FileWriter forniscono metodi per leggere e scrivere file in un file system in sandbox. Sebbene sia asincrono, non è consigliato perché è disponibile solo nei browser basati su Chromium.
Quanto posso archiviare?
In breve, molto, almeno un paio di centinaia di megabyte e potenzialmente centinaia di gigabyte o più. Le implementazioni del browser variano, ma la quantità di spazio di archiviazione disponibile si basa in genere sulla quantità di spazio di archiviazione disponibile sul dispositivo.
- Chrome consente al browser di utilizzare fino all'80% dello spazio su disco totale. Un'origine può utilizzare fino al 60% dello spazio su disco totale. Puoi utilizzare l'API StorageManager per determinare la quota massima disponibile. Altri browser basati su Chromium potrebbero essere diversi.
- In modalità di navigazione in incognito, Chrome riduce la quantità di spazio di archiviazione che un'origine può utilizzare a circa il 5% dello spazio su disco totale.
- Se l'utente ha attivato l'opzione "Cancella cookie e dati dei siti alla chiusura di tutte le finestre" in Chrome, la quota di spazio di archiviazione viene ridotta in modo significativo a un massimo di circa 300 MB.
- Firefox consente al browser di utilizzare fino al 50% dello spazio su disco libero. Un
gruppo
eTLD+1 (ad es.
example.com,www.example.comefoo.bar.example.com) può utilizzare fino a 2 GB. Puoi utilizzare l' API StorageManager per determinare la quantità di spazio ancora disponibile. - Safari (sia per computer che per dispositivi mobili) sembra consentire circa 1 GB. Quando viene raggiunto il limite, Safari chiede all'utente di aumentare il limite con incrementi di 200 MB. Non sono riuscito a trovare alcuna documentazione ufficiale in merito.
- Se una PWA viene aggiunta alla schermata Home di Safari per dispositivi mobili, viene creato un nuovo container di archiviazione e non viene condiviso nulla tra la PWA e Safari per dispositivi mobili. Una volta raggiunta la quota per una PWA installata, non sembra esistere alcun modo per richiedere spazio di archiviazione aggiuntivo.
In passato, se un sito superava una determinata soglia di dati archiviati, il browser chiedeva all'utente di concedere l'autorizzazione a utilizzare più dati. Ad esempio, se l'origine utilizzava più di 50 MB, il browser chiedeva all'utente di consentire l'archiviazione di un massimo di 100 MB, quindi chiedeva di nuovo con incrementi di 50 MB.
Oggi, la maggior parte dei browser moderni non chiede all'utente e consente a un sito di utilizzare fino alla quota assegnata. L'eccezione sembra essere Safari, che chiede quando viene superata la quota di spazio di archiviazione, richiedendo l'autorizzazione ad aumentare la quota allocata. Se un'origine tenta di utilizzare più della quota assegnata, i tentativi successivi di scrivere dati non andranno a buon fine.
Come posso controllare la quantità di spazio di archiviazione disponibile?
In molti browser, puoi utilizzare l' API StorageManager per determinare la quantità di spazio di archiviazione disponibile per l'origine e la quantità di spazio di archiviazione utilizzata. Riporta il numero totale di byte utilizzati da IndexedDB e dall'API Cache e consente di calcolare lo spazio di archiviazione rimanente approssimativo disponibile.
if (navigator.storage && navigator.storage.estimate) {
const quota = await navigator.storage.estimate();
// quota.usage -> Number of bytes used.
// quota.quota -> Maximum number of bytes available.
const percentageUsed = (quota.usage / quota.quota) * 100;
console.log(`You've used ${percentageUsed}% of the available storage.`);
const remaining = quota.quota - quota.usage;
console.log(`You can write up to ${remaining} more bytes.`);
}
Devi rilevare gli errori di superamento della quota (vedi di seguito). In alcuni casi, è possibile che la quota disponibile superi la quantità effettiva di spazio di archiviazione disponibile.
Ispeziona
Durante lo sviluppo, puoi utilizzare gli Strumenti di sviluppo del browser per ispezionare i diversi tipi di spazio di archiviazione e cancellare tutti i dati archiviati.
In Chrome 88 è stata aggiunta una nuova funzionalità che consente di sostituire la quota di spazio di archiviazione del sito nel riquadro Spazio di archiviazione. Questa funzionalità ti consente di simulare diversi dispositivi e testare il comportamento delle tue app in scenari di bassa disponibilità del disco. Vai ad Applicazione, poi a Spazio di archiviazione, seleziona la casella di controllo Simula quota di spazio di archiviazione personalizzata e inserisci un numero valido per simulare la quota di spazio di archiviazione.
Durante la stesura di questa guida, ho scritto un semplice strumento per tentare di utilizzare rapidamente la maggior quantità di spazio di archiviazione possibile. È un modo rapido per sperimentare diversi meccanismi di archiviazione e vedere cosa succede quando utilizzi tutta la quota.
Come gestire il superamento della quota?
Cosa devi fare quando superi la quota? La cosa più importante è rilevare e gestire sempre gli errori di scrittura, che si tratti di un QuotaExceededError o di altro. Poi, a seconda della progettazione dell'app, decidi come gestirla.
Ad esempio, elimina i contenuti a cui non è stato eseguito l'accesso da molto tempo, rimuovi i dati in base alle dimensioni o fornisci agli utenti un modo per scegliere cosa eliminare.
Sia IndexedDB sia l'API Cache generano un DOMError denominato QuotaExceededError quando hai superato la quota disponibile.
IndexedDB
Se l'origine ha superato la quota, i tentativi di scrittura in IndexedDB non andranno a buon fine. Verrà chiamato il gestore onabort() della transazione, passando un evento.
L'evento includerà un DOMException nella proprietà error. Se controlli il name dell'errore, verrà restituito QuotaExceededError.
const transaction = idb.transaction(['entries'], 'readwrite');
transaction.onabort = function(event) {
const error = event.target.error; // DOMException
if (error.name == 'QuotaExceededError') {
// Fallback code goes here
}
};
API Cache
Se l'origine ha superato la quota, i tentativi di scrittura nell'API Cache verranno rifiutati con un DOMException QuotaExceededError.
try {
const cache = await caches.open('my-cache');
await cache.add(new Request('/sample1.jpg'));
} catch (err) {
if (error.name === 'QuotaExceededError') {
// Fallback code goes here
}
}
Come funziona l'eliminazione?
Lo spazio di archiviazione web è suddiviso in due bucket: "Best Effort" e "Persistent". Best effort significa che lo spazio di archiviazione può essere cancellato dal browser senza interrompere l'utente, ma è meno durevole per i dati a lungo termine o critici. Lo spazio di archiviazione permanente non viene cancellato automaticamente quando lo spazio di archiviazione è insufficiente. L'utente deve cancellare manualmente questo spazio di archiviazione (tramite le impostazioni del browser).
Per impostazione predefinita, i dati di un sito (inclusi IndexedDB, API Cache e così via) rientrano nella categoria Best Effort, il che significa che, a meno che un sito non abbia richiesto lo spazio di archiviazione permanente, il browser può eliminare i dati del sito a sua discrezione, ad esempio quando lo spazio sul dispositivo è insufficiente.
Il criterio di eliminazione per Best Effort è:
- I browser basati su Chromium inizieranno a eliminare i dati quando il browser esaurisce lo spazio, cancellando prima tutti i dati del sito dall'origine utilizzata meno di recente, poi quella successiva, finché il browser non supera più il limite.
- Firefox inizierà a eliminare i dati quando lo spazio su disco disponibile è pieno, cancellando prima tutti i dati del sito dall'origine utilizzata meno di recente, poi quella successiva, finché il browser non supera più il limite.
- In precedenza, Safari non eliminava i dati, ma di recente ha implementato un nuovo limite di sette giorni per tutto lo spazio di archiviazione scrivibile (vedi di seguito).
A partire da iOS e iPadOS 13.4 e Safari 13.1 su macOS, esiste un limite di sette giorni per tutto lo spazio di archiviazione scrivibile tramite script, inclusi IndexedDB, la registrazione dei service worker e l'API Cache. Ciò significa che Safari eliminerà tutti i contenuti dalla cache dopo sette giorni di utilizzo di Safari se l'utente non interagisce con il sito. Questo criterio di eliminazione non si applica alle PWA installate che sono state aggiunte alla schermata Home. Per tutti i dettagli, consulta la sezione Blocco completo dei cookie di terze parti e altro ancora nel blog WebKit.
Bucket di archiviazione
L'idea principale dell'API Storage Buckets è quella di consentire ai siti di creare più bucket di archiviazione, in cui il browser può scegliere di eliminare ogni bucket indipendentemente dagli altri. In questo modo, gli sviluppatori possono specificare la priorità di eliminazione per assicurarsi che i dati più importanti non vengano eliminati.
Bonus: perché utilizzare un wrapper per IndexedDB
IndexedDB è un'API di basso livello che richiede una configurazione significativa prima dell'uso, il che può essere particolarmente difficile per l'archiviazione di dati a bassa complessità. A differenza della maggior parte delle API moderne basate su promesse, è basata su eventi. I wrapper di promesse come idb per IndexedDB nascondono alcune delle funzionalità avanzate, ma soprattutto nascondono il meccanismo complesso (ad es. transazioni, controllo delle versioni dello schema) fornito con la libreria IndexedDB.
Bonus: SQLite Wasm
Dopo che SQL web è stato ritirato e rimosso da Chrome, Google ha collaborato con i gestori del popolare database SQLite per offrire una sostituzione di SQL web basata su SQLite. Per informazioni dettagliate su come utilizzarlo, consulta la sezione SQLite Wasm nel browser supportato dall'Origin Private File System.
Conclusione
Sono finiti i tempi dello spazio di archiviazione limitato e della richiesta all'utente di archiviare sempre più dati. I siti possono archiviare in modo efficace tutte le risorse e i dati necessari per l'esecuzione. Utilizzando l'API StorageManager, puoi determinare la quantità di spazio disponibile e la quantità di spazio utilizzata. E con spazio di archiviazione permanente, a meno che l'utente non lo rimuova, puoi proteggerlo dall'eliminazione.
Risorse aggiuntive
Grazie
Un ringraziamento speciale a Jarryd Goodman, Phil Walton, Eiji Kitamura, Daniel Murphy, Darwin Huang, Josh Bell, Marijn Kruisselbrink e Victor Costan per aver esaminato questa guida. Grazie a Eiji Kitamura, Addy Osmani e Marc Cohen che hanno scritto gli articoli originali su cui si basa questa guida. Eiji ha scritto uno strumento utile chiamato Browser Storage Abuser che è stato utile per convalidare il comportamento attuale. Ti consente di archiviare la maggior quantità di dati possibile e di visualizzare i limiti di spazio di archiviazione nel browser. Grazie a François Beaufort che ha approfondito Safari per scoprire i limiti di spazio di archiviazione e a Thomas Steiner per aver aggiunto informazioni sull'Origin Private File System, sui bucket di archiviazione, su SQLite Wasm e per un aggiornamento generale dei contenuti nel 2024.