Penyimpanan untuk web

Ada banyak opsi berbeda untuk menyimpan data di browser. Manakah yang paling sesuai dengan kebutuhan Anda?

Koneksi internet bisa turun-naik atau tidak ada saat di perjalanan, yang merupakan sebab dukungan offline dan kinerja yang bisa diandalkan menjadi fitur umum di aplikasi web progresif. Bahkan di lingkungan nirkabel yang sempurna, penggunaan yang bijak atas caching dan teknik penyimpanan lainnya dapat secara substansial meningkatkan pengalaman pengguna. Ada beberapa cara untuk meng-cache resource aplikasi statis (HTML, JavaScript, CSS, gambar, dll.), dan data (data pengguna, artikel berita, dll.). Namun, manakah solusi terbaiknya? Berapa banyak data yang dapat Anda simpan? Bagaimana cara mencegahnya agar tidak dihapus?

Apa yang harus saya gunakan?

Berikut adalah rekomendasi umum untuk menyimpan resource:

IndexedDB, OPFS, dan Cache Storage API didukung di setiap browser modern. Fungsi ini bersifat asinkron, dan tidak akan memblokir thread utama (tetapi ada juga varian sinkron OPFS yang tersedia secara eksklusif di pekerja web). Fungsi ini dapat diakses dari objek window, pekerja web, dan pekerja layanan, sehingga memungkinkan Anda menggunakannya di mana saja dalam kode Anda.

Bagaimana dengan mekanisme penyimpanan lainnya?

Ada beberapa mekanisme penyimpanan lain yang tersedia di browser, tetapi memiliki penggunaan terbatas dan dapat menyebabkan masalah performa yang signifikan.

SessionStorage bersifat khusus tab, dan dicakup untuk masa aktif tab. Hal ini mungkin berguna untuk menyimpan sejumlah kecil informasi khusus sesi, misalnya kunci IndexedDB. Fungsi ini harus digunakan dengan hati-hati karena bersifat sinkron dan akan memblokir thread utama. File ini dibatasi hingga sekitar 5 MB dan hanya dapat berisi string. Karena khusus tab, tidak dapat diakses dari pekerja web atau pekerja layanan.

LocalStorage harus dihindari karena bersifat sinkron dan akan memblokir thread utama. File ini dibatasi hingga sekitar 5 MB dan hanya dapat berisi string. LocalStorage tidak dapat diakses dari pekerja web atau pekerja layanan.

Cookie memiliki kegunaannya, tetapi tidak boleh digunakan untuk penyimpanan. Cookie dikirim dengan setiap permintaan HTTP, sehingga menyimpan lebih dari sedikit data akan meningkatkan ukuran setiap permintaan web secara signifikan. Fungsi ini bersifat sinkron, dan tidak dapat diakses dari pekerja web. Seperti LocalStorage dan SessionStorage, cookie hanya dibatasi untuk string.

File System Access API dirancang untuk memungkinkan pengguna membaca dan mengedit file di sistem file lokal mereka. Pengguna harus memberikan izin sebelum halaman dapat membaca atau menulis ke file lokal apa pun, dan izin tidak dipertahankan di seluruh sesi, kecuali jika handle file di-cache di IndexedDB. File System Access API paling cocok untuk kasus penggunaan seperti editor, tempat Anda perlu membuka file, mengubahnya, lalu mungkin menyimpan kembali perubahan ke file.

File System API dan FileWriter API menyediakan metode untuk membaca dan menulis file ke sistem file dengan sandbox. Meskipun asinkron, metode ini tidak direkomendasikan karena hanya tersedia di browser berbasis Chromium.

Berapa banyak yang dapat saya simpan?

Singkatnya, banyak, setidaknya beberapa ratus megabyte, dan berpotensi ratusan gigabyte atau lebih. Implementasi browser bervariasi, tetapi jumlah penyimpanan yang tersedia biasanya didasarkan pada jumlah penyimpanan yang tersedia di perangkat.

  • Chrome memungkinkan browser menggunakan hingga 80% total ruang disk. Origin dapat menggunakan hingga 60% dari total ruang disk. Anda dapat menggunakan StorageManager API untuk menentukan kuota maksimum yang tersedia. Browser berbasis Chromium lainnya mungkin berbeda.
    • Dalam mode Samaran, Chrome mengurangi jumlah penyimpanan yang dapat digunakan origin menjadi sekitar 5% dari total ruang disk.
    • Jika pengguna telah mengaktifkan "Hapus cookie dan data situs saat Anda menutup semua jendela" di Chrome, kuota penyimpanan akan dikurangi secara signifikan menjadi maksimum sekitar 300 MB.
  • Firefox memungkinkan browser menggunakan hingga 50% ruang disk kosong. Grup eTLD+1 (misalnya, example.com, www.example.com, dan foo.bar.example.com) dapat menggunakan hingga 2 GB. Anda dapat menggunakan StorageManager API untuk menentukan jumlah ruang yang masih tersedia.
  • Safari (baik desktop maupun seluler) tampaknya mengizinkan sekitar 1 GB. Saat batas tercapai, Safari akan meminta pengguna, meningkatkan batas dalam inkremen 200 MB. Saya tidak dapat menemukan dokumentasi resmi tentang hal ini.
    • Jika ditambahkan ke layar utama di Safari seluler, PWA akan membuat penampung penyimpanan baru, dan tidak ada yang dibagikan antara PWA dan Safari seluler. Setelah kuota tercapai untuk PWA yang diinstal, tampaknya tidak ada cara untuk meminta penyimpanan tambahan.

Sebelumnya, jika situs melampaui nilai minimum data yang disimpan, browser akan meminta pengguna untuk memberikan izin agar dapat menggunakan lebih banyak data. Misalnya, jika origin menggunakan lebih dari 50 MB, browser akan meminta pengguna untuk mengizinkannya menyimpan hingga 100 MB, lalu meminta lagi dengan penambahan 50 MB.

Saat ini, sebagian besar browser modern tidak akan meminta pengguna, dan akan mengizinkan situs menggunakan kuota yang ditetapkan. Pengecualian tampaknya adalah Safari, yang akan meminta izin untuk meningkatkan kuota yang dialokasikan saat kuota penyimpanan terlampaui. Jika origin mencoba menggunakan lebih dari kuota yang ditetapkan, upaya lebih lanjut untuk menulis data akan gagal.

Bagaimana cara memeriksa kapasitas penyimpanan yang tersedia?

Di banyak browser, Anda dapat menggunakan StorageManager API untuk menentukan jumlah penyimpanan yang tersedia untuk origin, dan jumlah penyimpanan yang digunakan. Fungsi ini melaporkan jumlah total byte yang digunakan oleh IndexedDB dan Cache API, serta memungkinkan penghitungan perkiraan ruang penyimpanan yang tersisa.

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.`);
}

Anda harus menangkap error kelebihan kuota (lihat di bawah). Dalam beberapa kasus, kuota yang tersedia dapat melebihi jumlah penyimpanan yang sebenarnya tersedia.

Periksa

Selama pengembangan, Anda dapat menggunakan DevTools browser untuk memeriksa berbagai jenis penyimpanan, dan menghapus semua data yang disimpan.

Fitur baru telah ditambahkan di Chrome 88 yang memungkinkan Anda mengganti kuota penyimpanan situs di Panel Penyimpanan. Fitur ini memberi Anda kemampuan untuk menyimulasikan perangkat yang berbeda dan menguji perilaku aplikasi dalam skenario ketersediaan disk yang rendah. Buka Aplikasi, lalu Penyimpanan, aktifkan kotak centang Simulasi kuota penyimpanan kustom, dan masukkan angka yang valid untuk menyimulasikan kuota penyimpanan.

Saat mengerjakan panduan ini, saya menulis alat sederhana untuk mencoba menggunakan penyimpanan sebanyak mungkin dengan cepat. Ini adalah cara cepat untuk bereksperimen dengan berbagai mekanisme penyimpanan, dan melihat apa yang terjadi saat Anda menggunakan semua kuota.

Bagaimana cara menangani kelebihan kuota?

Apa yang harus Anda lakukan jika melebihi kuota? Yang terpenting, Anda harus selalu menangkap dan menangani error tulis, baik itu QuotaExceededError atau hal lain. Kemudian, bergantung pada desain aplikasi Anda, tentukan cara menanganinya. Misalnya, hapus konten yang sudah lama tidak diakses, hapus data berdasarkan ukuran, atau berikan cara bagi pengguna untuk memilih konten yang ingin dihapus.

IndexedDB dan Cache API menampilkan DOMError bernama QuotaExceededError saat Anda telah melampaui kuota yang tersedia.

IndexedDB

Jika origin telah melampaui kuotanya, upaya menulis ke IndexedDB akan gagal. Pengendali onabort() transaksi akan dipanggil, yang meneruskan peristiwa. Peristiwa akan menyertakan DOMException di properti error. Memeriksa error name akan menampilkan 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
  }
};

Cache API

Jika origin telah melampaui kuotanya, upaya untuk menulis ke Cache API akan ditolak dengan QuotaExceededError DOMException.

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

Bagaimana cara kerja penggusuran?

Penyimpanan web dikategorikan ke dalam dua bucket, "Upaya Terbaik" dan "Persisten". Upaya terbaik berarti penyimpanan dapat dihapus oleh browser tanpa mengganggu pengguna, tetapi kurang tahan lama untuk data jangka panjang atau data penting. Penyimpanan persisten tidak otomatis dihapus jika penyimpanan tinggal sedikit. Pengguna perlu mengosongkan penyimpanan ini secara manual (melalui setelan browser).

Secara default, data situs (termasuk IndexedDB, Cache API, dll.) termasuk dalam kategori upaya terbaik, yang berarti kecuali jika situs telah meminta penyimpanan persisten, browser dapat menghapus data situs sesuai kebijaksanaannya, misalnya, saat penyimpanan perangkat rendah.

Kebijakan penghapusan untuk upaya terbaik adalah:

  • Browser berbasis Chromium akan mulai menghapus data saat browser kehabisan ruang, dengan menghapus semua data situs dari origin yang paling jarang digunakan terlebih dahulu, lalu yang berikutnya, hingga browser tidak lagi melebihi batas.
  • Firefox akan mulai menghapus data saat ruang disk yang tersedia terisi penuh, dengan menghapus semua data situs dari origin yang paling lama tidak digunakan terlebih dahulu, lalu yang berikutnya, hingga browser tidak lagi melebihi batas.
  • Safari sebelumnya tidak menghapus data, tetapi baru-baru ini menerapkan batas tujuh hari baru pada semua penyimpanan yang dapat ditulis (lihat di bawah).

Mulai iOS dan iPadOS 13.4 serta Safari 13.1 di macOS, ada batas tujuh hari untuk semua penyimpanan skrip yang dapat ditulis, termasuk IndexedDB, pendaftaran pekerja layanan, dan Cache API. Artinya, Safari akan menghapus semua konten dari cache setelah tujuh hari penggunaan Safari jika pengguna tidak berinteraksi dengan situs. Kebijakan penghapusan ini tidak berlaku untuk PWA yang diinstal yang telah ditambahkan ke layar utama. Lihat Pemblokiran Cookie Pihak Ketiga Lengkap dan Lainnya di blog WebKit untuk mengetahui detail selengkapnya.

Bucket penyimpanan

Ide inti Storage Buckets API adalah memberikan kemampuan kepada situs untuk membuat beberapa bucket penyimpanan, tempat browser dapat memilih untuk menghapus setiap bucket secara terpisah dari bucket lainnya. Hal ini memungkinkan developer menentukan prioritas penghapusan untuk memastikan data yang paling berharga tidak dihapus.

Bonus: Alasan menggunakan wrapper untuk IndexedDB

IndexedDB adalah API tingkat rendah yang memerlukan penyiapan yang signifikan sebelum digunakan, yang dapat sangat merepotkan untuk menyimpan data dengan kompleksitas rendah. Tidak seperti sebagian besar API berbasis promise modern, API ini berbasis peristiwa. Wrapper promise seperti idb untuk IndexedDB menyembunyikan beberapa fitur canggih, tetapi yang lebih penting, menyembunyikan mesin kompleks (misalnya, transaksi, pembuatan versi skema) yang disertakan dengan library IndexedDB.

Bonus: SQLite Wasm

Setelah Web SQL tidak digunakan lagi dan dihapus dari Chrome, Google bekerja sama dengan pengelola database SQLite yang populer untuk menawarkan pengganti Web SQL berdasarkan SQLite. Baca SQLite Wasm di browser yang didukung oleh Sistem File Pribadi Origin untuk mengetahui detail tentang cara menggunakannya.

Kesimpulan

Tidak ada lagi penyimpanan terbatas dan meminta pengguna untuk menyimpan lebih banyak data. Situs dapat menyimpan semua resource dan data yang diperlukan untuk dijalankan secara efektif. Dengan menggunakan StorageManager API, Anda dapat menentukan jumlah yang tersedia untuk Anda, dan jumlah yang telah Anda gunakan. Selain itu, dengan penyimpanan persisten, kecuali jika pengguna menghapusnya, Anda dapat melindunginya dari penghapusan.

Referensi lainnya

Terima kasih

Terima kasih khusus kepada Jarryd Goodman, Phil Walton, Eiji Kitamura, Daniel Murphy, Darwin Huang, Josh Bell, Marijn Kruisselbrink, dan Victor Costan yang telah meninjau panduan ini. Terima kasih kepada Eiji Kitamura, Addy Osmani, dan Marc Cohen yang menulis artikel asli yang menjadi dasar artikel ini. Eiji menulis alat yang berguna yang disebut Browser Storage Abuser yang berguna dalam memvalidasi perilaku saat ini. Dengan begitu, Anda dapat menyimpan data sebanyak mungkin dan melihat batas penyimpanan di browser. Terima kasih kepada François Beaufort yang melakukan penggalian di Safari untuk mengetahui batas penyimpanannya dan kepada Thomas Steiner karena telah menambahkan informasi tentang sistem file pribadi asal, bucket penyimpanan, SQLite Wasm, dan pembaruan konten secara keseluruhan pada tahun 2024.

Gambar hero adalah karya Guillaume Bolduc di Unsplash.