KV Storage - de eerste ingebouwde module op internet

Browserleveranciers en experts op het gebied van webprestaties hebben het grootste deel van het afgelopen decennium gezegd dat localStorage traag is en dat webontwikkelaars ermee moeten stoppen.

Eerlijk gezegd hebben de mensen die dit zeggen geen ongelijk. localStorage is een synchrone API die de hoofdthread blokkeert, en elke keer dat u deze opent, voorkomt u mogelijk dat uw pagina interactief is.

Het probleem is dat de localStorage API zo verleidelijk eenvoudig is, en het enige asynchrone alternatief voor localStorage is IndexedDB , dat (laten we eerlijk zijn) niet bekend staat om zijn gebruiksgemak of gastvrije API.

Ontwikkelaars hebben dus de keuze tussen iets dat moeilijk te gebruiken is en iets dat slecht is voor de prestaties. En hoewel er bibliotheken zijn die de eenvoud van de localStorage API bieden terwijl ze feitelijk gebruik maken van asynchrone opslag-API's onder de motorkap, brengt het opnemen van een van die bibliotheken in uw app kosten met zich mee die zo groot zijn als de bestandsgrootte en die een beslag kunnen leggen op uw prestatiebudget .

Maar wat als het mogelijk zou zijn om de prestaties van een asynchrone opslag-API te verkrijgen met de eenvoud van de localStorage API, zonder de kosten voor de bestandsgrootte te hoeven betalen?

Nou ja, binnenkort kan dat zo zijn. Chrome experimenteert met een nieuwe functie die bekend staat als ingebouwde modules , en de eerste die we van plan zijn te leveren is een asynchrone sleutel/waarde-opslagmodule genaamd KV Storage .

Maar voordat ik inga op de details van de KV Storage-module, wil ik eerst uitleggen wat ik bedoel met ingebouwde modules .

Wat zijn inbouwmodules?

Ingebouwde modules zijn net als gewone JavaScript- modules , behalve dat ze niet hoeven te worden gedownload omdat ze bij de browser worden geleverd.

Net als traditionele web-API's moeten ingebouwde modules een standaardisatieproces doorlopen. Elke module heeft zijn eigen specificatie die een ontwerpbeoordeling en positieve tekenen van ondersteuning van zowel webontwikkelaars als andere browserleveranciers vereist voordat deze kan worden verzonden. (In Chrome volgen ingebouwde modules hetzelfde startproces dat we gebruiken om alle nieuwe API's te implementeren en te verzenden.)

In tegenstelling tot traditionele web-API's zijn ingebouwde modules niet wereldwijd zichtbaar; ze zijn alleen beschikbaar via imports .

Het niet wereldwijd beschikbaar stellen van ingebouwde modules heeft veel voordelen: ze voegen geen overhead toe aan het opstarten van een nieuwe JavaScript-runtimecontext (bijvoorbeeld een nieuw tabblad, worker of service worker), en ze verbruiken geen geheugen of CPU tenzij ze daadwerkelijk worden geïmporteerd. Bovendien lopen ze niet het risico dat er botsingen ontstaan ​​met andere variabelen die in uw code zijn gedefinieerd.

Om een ​​ingebouwde module te importeren, gebruikt u het voorvoegsel std: gevolgd door de identificatie van de ingebouwde module. In ondersteunde browsers kunt u bijvoorbeeld de KV Storage-module importeren met de volgende code (zie hieronder voor het gebruik van een KV Storage-polyfill in niet-ondersteunde browsers ):

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

De KV Storage-module

De KV Storage-module is qua eenvoud vergelijkbaar met de localStorage API , maar de API-vorm komt eigenlijk dichter bij een JavaScript Map . In plaats van getItem() , setItem() en removeItem() heeft het get() , set() en delete() . Het heeft ook andere kaartachtige methoden die niet beschikbaar zijn voor localStorage , zoals keys() , values() en entries() , en net als Map hoeven de sleutels geen strings te zijn. Ze kunnen van elk gestructureerd en serialiseerbaar type zijn.

In tegenstelling tot Map retourneren alle KV Storage-methoden beloftes of asynchrone iterators (aangezien het belangrijkste punt van deze module is dat deze niet synchroon is, in tegenstelling tot localStorage ). Om de volledige API in detail te zien, kunt u de specificatie raadplegen.

Zoals je misschien hebt gemerkt uit het bovenstaande codevoorbeeld, heeft de KV Storage-module één standaard storage en één met de naam export StorageArea .

storage is een exemplaar van de klasse StorageArea met de naam 'default' en is wat ontwikkelaars het vaakst zullen gebruiken in hun applicatiecode. De klasse StorageArea is bedoeld voor gevallen waarin aanvullende isolatie nodig is (bijvoorbeeld een bibliotheek van derden die gegevens opslaat en conflicten wil vermijden met gegevens die zijn opgeslagen via de storage ). StorageArea gegevens worden opgeslagen in een IndexedDB-database met de naam kv-storage:${name} , waarbij naam de naam is van de StorageArea instantie.

Hier is een voorbeeld van hoe u de KV Storage-module in uw code kunt gebruiken:

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();

Wat moet ik doen als een browser een ingebouwde module niet ondersteunt?

Als u bekend bent met het gebruik van native JavaScript-modules in browsers, weet u waarschijnlijk dat (tenminste tot nu toe) het importeren van iets anders dan een URL een fout zal genereren. En std:kv-storage is geen geldige URL.

Dat roept dus de vraag op: moeten we wachten totdat alle browsers ingebouwde modules ondersteunen voordat we deze in onze code kunnen gebruiken? Gelukkig is het antwoord nee!

Je kunt ingebouwde modules daadwerkelijk gebruiken zodra zelfs maar één browser ze ondersteunt, dankzij de hulp van een andere functie waarmee we experimenteren , genaamd import maps .

Kaarten importeren

Importkaarten zijn in wezen een mechanisme waarmee ontwikkelaars ID's kunnen importeren in een of meer alternatieve ID's.

Dit is krachtig omdat het u een manier biedt om (tijdens runtime) te wijzigen hoe een browser een bepaalde import-ID in uw hele applicatie omzet.

In het geval van ingebouwde modules kunt u hierdoor in uw applicatiecode verwijzen naar een polyfill van de module, maar een browser die de ingebouwde module ondersteunt, kan die versie in plaats daarvan laden!

Hier ziet u hoe u een importkaart zou declareren om dit te laten werken met de KV Storage-module:

<!-- 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>

Het belangrijkste punt in de bovenstaande code is dat de URL /path/to/kv-storage-polyfill.mjs wordt toegewezen aan twee verschillende bronnen: std:kv-storage en vervolgens opnieuw de originele URL, /path/to/kv-storage-polyfill.mjs .

Dus wanneer de browser een importinstructie tegenkomt die naar die URL verwijst ( /path/to/kv-storage-polyfill.mjs ), probeert hij eerst std:kv-storage te laden, en als dat niet lukt, valt hij terug op laden /path/to/kv-storage-polyfill.mjs .

Nogmaals, de magie hier is dat de browser geen importkaarten of ingebouwde modules hoeft te ondersteunen om deze techniek te laten werken, aangezien de URL die wordt doorgegeven aan de importinstructie de URL is voor de polyfill. De polyfill is eigenlijk geen terugval, het is de standaard. De ingebouwde module is een progressieve uitbreiding!

Hoe zit het met browsers die helemaal geen modules ondersteunen?

Om importtoewijzingen te gebruiken om ingebouwde modules voorwaardelijk te laden, moet je daadwerkelijk import gebruiken, wat ook betekent dat je modulescripts moet gebruiken, dat wil zeggen <script type="module"> .

Momenteel ondersteunt meer dan 80% van de browsers modules , en voor browsers die dat niet doen, kunt u de module/nomodule-techniek gebruiken om een ​​oudere bundel te bedienen. Houd er rekening mee dat u bij het genereren van uw nomodule build alle polyfills moet opnemen, omdat u zeker weet dat browsers die geen modules ondersteunen, zeker geen ingebouwde modules zullen ondersteunen.

KV Storage-demo

Om te illustreren dat het mogelijk is om ingebouwde modules te gebruiken terwijl je nog steeds oudere browsers ondersteunt, heb ik een demo samengesteld die alle hierboven beschreven technieken bevat en die vandaag de dag in alle browsers draait:

  • Browsers die modules ondersteunen, kaarten importeren en de ingebouwde module laden geen onnodige code.
  • Browsers die modules ondersteunen en kaarten importeren, maar de ingebouwde module niet ondersteunen, laden de KV Storage polyfill (via de modulelader van de browser).
  • Browsers die modules ondersteunen, maar geen importkaarten ondersteunen, laden ook de KV Storage-polyfill (via de modulelader van de browser).
  • Browsers die helemaal geen modules ondersteunen, krijgen de KV Storage-polyfill in hun oudere bundel (geladen via <script nomodule> ).

De demo wordt gehost op Glitch, zodat u de bron kunt bekijken . Ik heb ook een gedetailleerde uitleg van de implementatie in de README . Kom gerust eens kijken als je benieuwd bent hoe hij in elkaar zit.

Om de ingebouwde module daadwerkelijk in actie te zien, moet u de demo in Chrome 74 of hoger laden met de vlag voor experimentele webplatformfuncties ingeschakeld ( chrome://flags/#enable-experimental-web-platform-features ).

U kunt verifiëren dat de ingebouwde module wordt geladen, omdat u het polyfill-script niet ziet in het bronpaneel in DevTools; in plaats daarvan zie je de ingebouwde moduleversie (leuk weetje: je kunt de broncode van de module daadwerkelijk inspecteren of er zelfs breekpunten in plaatsen!):

De bron van de KV Storage-module in Chrome DevTools

Geef ons alstublieft feedback

Deze introductie had u een voorproefje moeten geven van wat mogelijk is met ingebouwde modules. En hopelijk ben je enthousiast! We zouden het heel leuk vinden als ontwikkelaars de KV Storage-module (evenals alle nieuwe functies die hier worden besproken) uitproberen en ons feedback geven.

Hier zijn de GitHub-links waar u ons feedback kunt geven voor elk van de functies die in dit artikel worden genoemd:

Als uw site momenteel localStorage gebruikt, kunt u proberen over te schakelen naar de KV Storage API om te zien of deze aan al uw behoeften voldoet. En als u zich aanmeldt voor de proefversie van KV Storage Origin , kunt u deze functies vandaag nog daadwerkelijk implementeren. Al uw gebruikers zouden moeten profiteren van betere opslagprestaties en gebruikers van Chrome 74+ hoeven geen extra downloadkosten te betalen.