Penyimpanan KV - Modul Bawaan Pertama Web

Selama satu dekade terakhir, vendor browser dan pakar performa web telah mengatakan bahwa localStorage lambat, dan developer web sebaiknya berhenti menggunakannya.

Untuk bersikap adil, orang-orang itu mengatakan ini tidak salah. localStorage adalah API sinkron yang memblokir thread utama, dan setiap kali mengaksesnya, Anda berpotensi mencegah halaman Anda menjadi interaktif.

Masalahnya adalah localStorage API sangat sederhana, dan satu-satunya alternatif asinkron untuk localStorage adalah IndexedDB, yang (mari kita hadapi) tidak dikenal karena kemudahan penggunaan atau API yang ramah.

Jadi, developer memiliki pilihan antara sesuatu yang sulit digunakan dan sesuatu yang buruk untuk performa. Dan meskipun ada library yang menawarkan kemudahan localStorage API saat sebenarnya menggunakan API penyimpanan asinkron, termasuk salah satu library tersebut di aplikasi Anda yang memiliki biaya sebesar file dan dapat menghabiskan anggaran performa Anda.

Namun, bagaimana jika Anda dapat mendapatkan performa API penyimpanan asinkron dengan kemudahan API localStorage, tanpa harus membayar biaya ukuran file?

Mungkin akan segera ada. Chrome bereksperimen dengan fitur baru yang dikenal sebagai modul bawaan, dan fitur pertama yang kami rencanakan untuk dikirim adalah modul penyimpanan kunci/nilai asinkron yang disebut KV Storage.

Namun, sebelum membahas modul Penyimpanan KV secara mendetail, saya akan menjelaskan apa yang dimaksud dengan modul bawaan.

Apa yang dimaksud dengan modul bawaan?

Modul bawaan sama seperti modul JavaScript biasa, kecuali modul tersebut tidak perlu didownload karena disertakan bersama browser.

Seperti API web tradisional, modul bawaan harus melalui proses standardisasi — masing-masing modul akan memiliki spesifikasinya sendiri yang memerlukan peninjauan desain dan tanda dukungan positif dari developer web dan vendor browser lainnya sebelum dapat dikirimkan. (Di Chrome, modul bawaan akan mengikuti proses peluncuran yang sama dengan yang kami gunakan untuk mengimplementasikan dan mengirimkan semua API baru.)

Tidak seperti API web tradisional, modul bawaan tidak diekspos di cakupan global — modul tersebut hanya tersedia melalui impor.

Tidak mengekspos modul bawaan secara global memiliki banyak keuntungan: modul ini tidak akan menambah overhead untuk memulai konteks runtime JavaScript baru (mis. tab baru, pekerja, atau pekerja layanan), dan tidak akan memakai memori atau CPU kecuali jika benar-benar diimpor. Selain itu, skrip ini tidak berisiko menamai konflik dengan variabel lain yang ditentukan dalam kode Anda.

Untuk mengimpor modul bawaan, gunakan awalan std: yang diikuti dengan ID modul bawaan. Misalnya, di browser yang didukung, Anda dapat mengimpor modul Penyimpanan KV dengan kode berikut (lihat di bawah untuk mengetahui cara menggunakan polyfill Penyimpanan KV di browser yang tidak didukung):

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

Modul Penyimpanan KV

Modul Penyimpanan KV memiliki kesederhanaan yang mirip dengan localStorage API, tetapi bentuk API-nya sebenarnya lebih dekat dengan JavaScript Map. Alih-alih getItem(), setItem(), dan removeItem(), aplikasi ini memiliki get(), set(), dan delete(). Objek ini juga memiliki metode mirip peta lainnya yang tidak tersedia untuk localStorage, seperti keys(), values(), dan entries(), dan seperti Map, kuncinya tidak harus berupa string. Jenis data dapat berupa jenis yang dapat diserialisasi terstruktur.

Tidak seperti Map, semua metode KV Storage menampilkan promise atau iterator asinkron (karena poin utama modul ini adalah tidak sinkron, berbeda dengan localStorage). Untuk melihat API lengkap secara mendetail, Anda dapat melihat spesifikasi.

Seperti yang mungkin telah Anda lihat dari contoh kode di atas, modul Penyimpanan KV memiliki satu storage ekspor default dan satu lagi bernama ekspor StorageArea.

storage adalah instance class StorageArea dengan nama 'default', dan itulah yang paling sering digunakan developer dalam kode aplikasi mereka. Class StorageArea disediakan untuk kasus yang memerlukan isolasi tambahan (misalnya, library pihak ketiga yang menyimpan data dan ingin menghindari konflik dengan data yang disimpan melalui instance storage default). Data StorageArea disimpan dalam database IndexedDB dengan nama kv-storage:${name}, dengan nama tersebut adalah nama instance StorageArea.

Berikut adalah contoh cara menggunakan modul Penyimpanan KV dalam kode Anda:

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

Bagaimana jika browser tidak mendukung modul bawaan?

Jika sudah terbiasa menggunakan modul JavaScript native di browser, Anda mungkin mengetahui bahwa (setidaknya sampai sekarang) mengimpor apa pun selain URL akan menghasilkan error. Dan std:kv-storage bukan URL yang valid.

Oleh karena itu, timbul pertanyaan: apakah kita harus menunggu hingga semua browser mendukung modul bawaan sebelum kita dapat menggunakannya dalam kode? Untungnya, jawabannya adalah tidak.

Anda dapat benar-benar menggunakan modul bawaan segera setelah satu browser mendukungnya berkat bantuan fitur lain yang sedang bereksperimen dengan impor peta.

Mengimpor peta

Peta impor pada dasarnya adalah mekanisme yang memungkinkan developer untuk mengimpor alias ID ke satu atau beberapa ID alternatif.

Cara ini ampuh karena memberi Anda cara untuk mengubah (saat runtime) cara browser me-resolve ID impor tertentu di seluruh aplikasi Anda.

Untuk modul bawaan, Anda dapat mereferensikan polyfill modul dalam kode aplikasi, tetapi browser yang mendukung modul bawaan dapat memuat versi tersebut.

Berikut cara mendeklarasikan peta impor agar berfungsi dengan modul 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>

Poin utama dalam kode di atas adalah bahwa URL /path/to/kv-storage-polyfill.mjs dipetakan ke dua resource yang berbeda: std:kv-storage, lalu URL asli lagi, /path/to/kv-storage-polyfill.mjs.

Jadi, saat menemukan pernyataan impor yang merujuk pada URL tersebut (/path/to/kv-storage-polyfill.mjs), browser akan mencoba memuat std:kv-storage terlebih dahulu, dan jika tidak bisa, browser akan kembali ke pemuatan /path/to/kv-storage-polyfill.mjs.

Sekali lagi, keajaibannya adalah browser tidak perlu mendukung peta impor atau modul bawaan agar teknik ini berfungsi karena URL yang diteruskan ke pernyataan impor adalah URL untuk polyfill. Polyfill sebenarnya bukan pengganti, ini adalah default. Modul bawaan adalah peningkatan progresif.

Bagaimana dengan browser yang tidak mendukung modul sama sekali?

Untuk menggunakan peta impor guna memuat modul bawaan secara bersyarat, Anda harus benar-benar menggunakan pernyataan import, yang juga berarti Anda harus menggunakan skrip modul, yaitu <script type="module">.

Saat ini, lebih dari 80% browser mendukung modul, dan untuk browser yang tidak mendukung modul, Anda dapat menggunakan teknik modul/nomodule untuk menayangkan paket lama. Perhatikan bahwa saat membuat build nomodule, Anda harus menyertakan semua polyfill karena Anda tahu dengan pasti bahwa browser yang tidak mendukung modul pasti tidak akan mendukung modul bawaan.

Demo Penyimpanan KV

Untuk mengilustrasikan bahwa modul bawaan dapat digunakan sambil tetap mendukung browser lama, saya telah menyusun demo yang menggabungkan semua teknik yang dijelaskan di atas dan berjalan di semua browser saat ini:

  • Browser yang mendukung modul, mengimpor peta, dan modul bawaan tidak memuat kode yang tidak diperlukan.
  • Browser yang mendukung modul dan mengimpor peta tetapi tidak mendukung modul bawaan akan memuat polyfill KV Storage (melalui loader modul browser).
  • Browser yang mendukung modul tetapi tidak mendukung peta impor juga memuat polyfill KV Storage (melalui loader modul browser).
  • Browser yang tidak mendukung modul sama sekali mendapatkan polyfill Penyimpanan KV dalam paket lamanya (dimuat melalui <script nomodule>).

Demo ini dihosting di Glitch, sehingga Anda dapat melihat sumbernya. Kami juga memiliki penjelasan terperinci tentang implementasinya di README. Jangan ragu untuk melihatnya jika Anda ingin tahu bagaimana cara membuatnya.

Untuk benar-benar melihat cara kerja modul bawaan native, Anda harus memuat demo di Chrome 74 atau yang lebih baru dengan mengaktifkan tanda fitur platform web eksperimental (chrome://flags/#enable-experimental-web-platform-features).

Anda dapat memastikan bahwa modul bawaan sedang dimuat karena Anda tidak akan melihat skrip polyfill di panel sumber di DevTools; sebagai gantinya, Anda akan melihat versi modul bawaan (fakta menarik: Anda sebenarnya dapat memeriksa kode sumber modul atau bahkan memasukkan titik henti sementara di dalamnya.):

Sumber modul Penyimpanan KV di Chrome DevTools

Berikan masukan Anda

Pengantar ini seharusnya memberi Anda gambaran tentang apa yang dapat dilakukan dengan modul bawaan. Dan semoga, Anda bersemangat. Kami sangat mengharapkan developer untuk mencoba modul Penyimpanan KV (serta semua fitur baru yang dibahas di sini) dan memberi kami masukan.

Berikut link GitHub yang dapat Anda gunakan untuk memberikan masukan kepada kami terkait setiap fitur yang disebutkan dalam artikel ini:

Jika situs Anda saat ini menggunakan localStorage, Anda harus mencoba beralih ke KV Storage API untuk melihat apakah situs tersebut memenuhi semua kebutuhan Anda. Dan jika mendaftar ke uji coba origin KV Storage, Anda dapat men-deploy fitur ini sekarang. Semua pengguna Anda akan mendapatkan manfaat dari performa penyimpanan yang lebih baik, dan pengguna Chrome 74+ tidak perlu membayar biaya download tambahan.