KV Storage: il primo modulo integrato del Web

I fornitori di browser e gli esperti di prestazioni web sostengono che, nella parte migliore dell'ultimo decennio, localStorage è lento e gli sviluppatori web dovrebbero smettere di utilizzarlo.

Ad essere onesti, le persone che dicono questo non sono sbagliate. localStorage è un'API sincrona che blocca il thread principale. Ogni volta che vi accedi, impedisci potenzialmente che la tua pagina sia interattiva.

Il problema è che l'API localStorage è così allettantemente semplice e l'unica alternativa asincrona a localStorage è IndexedDB, che, ammettiamolo, non è nota per la sua facilità d'uso o per l'accoglienza dell'API.

Pertanto, per gli sviluppatori viene lasciata la possibilità di scegliere tra qualcosa di difficile da usare e qualcosa di scarso per le prestazioni. Sebbene siano librerie che offrono la semplicità dell'API localStorage con l'utilizzo effettivo di API di archiviazione asincrone, una di queste librerie nella tua app ha un costo per le dimensioni dei file e può incidere sul tuo budget per le prestazioni.

E se fosse possibile ottenere le prestazioni di un'API di archiviazione asincrona con la semplicità dell'API localStorage, senza dover pagare il costo della dimensione del file?

Bene, presto potrebbe esserci. Chrome sta sperimentando una nuova funzionalità nota come moduli integrati e la prima che stiamo progettando di distribuire è un modulo di archiviazione asincrono di chiavi/valore chiamato KV Storage.

Prima di entrare nei dettagli del modulo di archiviazione KV, vorrei spiegare cosa intendo per moduli integrati.

Cosa sono i moduli integrati?

I moduli integrati sono come i normali moduli JavaScript, ad eccezione del fatto che non devono essere scaricati perché sono forniti con il browser.

Come le API web tradizionali, i moduli integrati devono essere sottoposti a un processo di standardizzazione, ognuno caratterizzato da specifiche che richiedono una revisione della progettazione e segnali positivi di supporto da parte degli sviluppatori web e di altri fornitori di browser prima di poter essere spediti. In Chrome, i moduli integrati seguono lo stesso processo di lancio che utilizziamo per implementare e distribuire tutte le nuove API.)

A differenza delle API web tradizionali, i moduli integrati non sono esposti all'ambito globale, ma sono disponibili solo tramite importazioni.

La mancata esposizione dei moduli integrati a livello globale presenta numerosi vantaggi: non comporta alcuna overhead per l'avvio di un nuovo contesto di runtime JavaScript (ad es. una nuova scheda, un worker o un service worker) e non consuma memoria o CPU a meno che non vengano effettivamente importati. Inoltre, non corrono il rischio di collisioni di denominazione con altre variabili definite nel codice.

Per importare un modulo integrato, utilizza il prefisso std: seguito dall'identificatore del modulo integrato. Ad esempio, nei browser supportati, puoi importare il modulo KV Storage con il seguente codice (vedi di seguito per come utilizzare un polyfill di KV Storage nei browser non supportati):

import storage, {StorageArea} from 'std:kv-storage';

Il modulo di archiviazione KV

Il modulo KV Storage è simile nella sua semplicità all'API localStorage, ma la sua forma dell'API è in realtà più simile a un JavaScript Map. Invece di getItem(), setItem() e removeItem(), ha get(), set() e delete(). Presenta anche altri metodi simili a quelli delle mappe non disponibili per localStorage, come keys(), values() e entries(), e, come Map, le sue chiavi non devono essere stringhe. Possono essere di qualsiasi tipo di tipo strutturabile per la serietà.

A differenza di Map, tutti i metodi di archiviazione KV restituiscono promesse o iteratori asincroni (dal momento che il punto principale di questo modulo è che non è sincrono, a differenza di localStorage). Per visualizzare l'API completa in dettaglio, puoi fare riferimento alla specifica.

Come avrai notato nell'esempio di codice riportato sopra, il modulo Archiviazione KV ha un'esportazione predefinita storage e un'esportazione denominata StorageArea.

storage è un'istanza di classe StorageArea con il nome 'default' ed è quella che gli sviluppatori utilizzeranno più spesso nel codice dell'applicazione. La classe StorageArea viene fornita nei casi in cui è necessario un ulteriore isolamento (ad esempio, una libreria di terze parti che archivia i dati e vuole evitare conflitti con i dati archiviati tramite l'istanza storage predefinita). I dati StorageArea vengono archiviati in un database IndexedDB denominato kv-storage:${name}, dove il nome è il nome dell'istanza StorageArea.

Di seguito è riportato un esempio di come utilizzare il modulo Archiviazione KV nel codice:

import storage from 'std:kv-storage';

const main = async () => {
  const oldPreferences = await storage.get('preferences');

  document.querySelector('form').addEventListener('submit', async () => {
    const newPreferences = Object.assign({}, oldPreferences, {
      // Updated preferences go here...
    });

    await storage.set('preferences', newPreferences);
  });
};

main();

Cosa succede se un browser non supporta un modulo integrato?

Se hai familiarità con l'uso di moduli JavaScript nativi nei browser, probabilmente sai che (almeno fino a questo momento) l'importazione di elementi diversi da un URL genera un errore. Inoltre, std:kv-storage non è un URL valido.

Ciò solleva la domanda: dobbiamo aspettare che tutti i browser supportino i moduli integrati prima di poterli utilizzare nel nostro codice? Per fortuna, la risposta è no.

Puoi utilizzare i moduli integrati non appena sono supportati anche da un solo browser, grazie all'aiuto di un'altra funzionalità che stiamo sperimentando e chiamata mappe di importazione.

Importa mappe

Le mappe di importazione sono essenzialmente un meccanismo mediante il quale gli sviluppatori possono utilizzare alias di importazione di uno o più identificatori alternativi.

Si tratta di una funzionalità potente perché ti consente di modificare (in fase di runtime) il modo in cui un browser risolve un determinato identificatore di importazione nell'intera applicazione.

Nel caso dei moduli integrati, ciò consente di fare riferimento a un polyfill del modulo nel codice dell'applicazione, ma un browser che supporta il modulo integrato può invece caricare quella versione.

Ecco come dichiarare una mappa di importazione per farla funzionare con il modulo KV Storage:

<!-- The import map is inlined into your page -->
<script type="importmap">
{
  "imports": {
    "/path/to/kv-storage-polyfill.mjs": [
      "std:kv-storage",
      "/path/to/kv-storage-polyfill.mjs"
    ]
  }
}
</script>

<!-- Then any module scripts with import statements use the above map -->
<script type="module">
  import storage from '/path/to/kv-storage-polyfill.mjs';

  // Use `storage` ...
</script>

Il punto chiave nel codice riportato sopra è che l'URL /path/to/kv-storage-polyfill.mjs viene mappato a due risorse diverse: std:kv-storage e poi di nuovo l'URL originale, /path/to/kv-storage-polyfill.mjs.

Quindi, quando il browser rileva un'istruzione di importazione che fa riferimento all'URL (/path/to/kv-storage-polyfill.mjs), prova prima a caricare std:kv-storage. Se non riesce, torna a caricare /path/to/kv-storage-polyfill.mjs.

Ancora una volta, la magia è che il browser non deve supportare le mappe di importazione o moduli integrati per consentire il funzionamento di questa tecnica, poiché l'URL passato all'istruzione di importazione è l'URL del polyfill. Il polyfill non è in realtà un metodo di riserva, è il metodo predefinito. Il modulo integrato è un miglioramento progressivo.

E i browser che non supportano i moduli?

Per usare le mappe di importazione per caricare i moduli integrati in modo condizionale, devi utilizzare le istruzioni import, il che significa anche che devi usare gli script dei moduli, ad esempio <script type="module">.

Attualmente, più dell'80% dei browser supporta i moduli e, per i browser che non li supporta, puoi utilizzare la tecnica modulo/nomodule per pubblicare un bundle precedente. Tieni presente che quando generi la build nomodule dovrai includere tutti i polyfill perché hai la certezza che i browser che non supportano i moduli non supporteranno i moduli integrati.

Demo spazio di archiviazione KV

Per spiegare che è possibile usare i moduli integrati pur supportando i browser meno recenti, ho creato una demo che incorpora tutte le tecniche descritte in precedenza e che oggi viene eseguita in tutti i browser:

  • I browser che supportano i moduli, importano le mappe e il modulo integrato non caricano alcun codice non necessario.
  • I browser che supportano i moduli e importano mappe, ma non supportano il modulo integrato, caricano il polyfill KV Storage (tramite il caricatore di moduli del browser).
  • Anche i browser che supportano i moduli, ma non supportano l'importazione delle mappe, caricano il polyfill di Storage KV (tramite il caricatore di moduli del browser).
  • I browser che non supportano i moduli ricevono il polyfill dello spazio di archiviazione dei valori chiave nel loro bundle legacy (caricato tramite <script nomodule>).

La demo è ospitata su Glitch, quindi puoi visualizzarne l'origine. Puoi anche leggere una spiegazione dettagliata dell'implementazione nel file README. Dai un'occhiata se sei curioso di vedere com'è fatto.

Per vedere effettivamente il modulo nativo integrato in azione, devi caricare la demo in Chrome 74 o versioni successive con il flag delle funzionalità sperimentali della piattaforma web attivato (chrome://flags/#enable-experimental-web-platform-features).

Puoi verificare che il modulo integrato sia stato caricato perché non vedrai lo script polyfill nel riquadro di origine in DevTools; vedrai invece la versione del modulo integrato. Curiosità: puoi esaminare il codice sorgente del modulo o persino inserire i punti di interruzione al suo interno.

L&#39;origine del modulo Archiviazione KV in Chrome DevTools

Inviaci il tuo feedback

Questa introduzione dovrebbe darti un'idea di cosa si potrebbe fare con i moduli integrati. E spero che tu sia entusiasta. Ci piacerebbe davvero che gli sviluppatori provassero il modulo KV Storage (nonché tutte le nuove funzionalità descritte qui) e ci inviassero feedback.

Ecco i link GitHub dove puoi fornirci un feedback su ciascuna delle funzionalità menzionate in questo articolo:

Se il tuo sito attualmente utilizza localStorage, ti consigliamo di provare a passare all'API KV Storage per vedere se soddisfa tutte le tue esigenze. Se ti registri per la prova dell'origine di KV Storage, puoi eseguire il deployment di queste funzionalità oggi stesso. Tutti i tuoi utenti dovrebbero beneficiare di prestazioni di archiviazione migliori e gli utenti di Chrome 74 e versioni successive non dovranno pagare costi di download aggiuntivi.