Ada banyak opsi berbeda untuk menyimpan data di browser. Mana yang paling sesuai dengan kebutuhan Anda?
Koneksi internet dapat tidak stabil atau tidak ada saat bepergian, itulah sebabnya dukungan offline dan performa yang andal adalah fitur umum di aplikasi web progresif. Bahkan dalam lingkungan nirkabel yang sempurna, penggunaan cache dan teknik penyimpanan lainnya secara bijak dapat meningkatkan pengalaman pengguna secara signifikan. Ada beberapa cara untuk menyimpan dalam cache resource aplikasi statis Anda (HTML, JavaScript, CSS, gambar, dll.), dan data (data pengguna, artikel berita, dll.). Namun, mana solusi terbaiknya? Berapa banyak yang dapat Anda simpan? Bagaimana cara mencegahnya dikeluarkan?
Apa yang harus saya gunakan?
Berikut rekomendasi umum untuk menyimpan resource:
- Untuk resource jaringan yang diperlukan untuk memuat aplikasi Anda, gunakan Cache Storage API (bagian dari service worker).
- Untuk konten berbasis file, gunakan Origin Private File System (OPFS).
- Untuk data lain, gunakan IndexedDB (dengan wrapper promises).
IndexedDB, OPFS, dan Cache Storage API didukung di setiap browser modern.
API ini bersifat asinkron, dan tidak akan memblokir thread utama (tetapi ada juga varian sinkron OPFS yang hanya tersedia di pekerja web). Objek ini dapat diakses dari objek window, web worker, dan service worker, sehingga memungkinkan Anda menggunakannya di mana saja dalam kode.
Bagaimana dengan mekanisme penyimpanan lainnya?
Ada beberapa mekanisme penyimpanan lain yang tersedia di browser, tetapi penggunaannya terbatas dan dapat menyebabkan masalah performa yang signifikan.
SessionStorage khusus untuk tab, dan dicakup ke masa aktif tab. ID ini mungkin berguna untuk menyimpan sejumlah kecil informasi khusus sesi, misalnya kunci IndexedDB. Metode ini harus digunakan dengan hati-hati karena bersifat sinkron dan akan memblokir thread utama. Ukurannya dibatasi hingga sekitar 5 MB dan hanya dapat berisi string. Karena khusus untuk tab, API ini tidak dapat diakses dari pekerja web atau pekerja layanan.
LocalStorage harus dihindari karena bersifat sinkron dan akan memblokir thread utama. Ukurannya 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, jadi menyimpan data lebih dari sedikit akan meningkatkan ukuran setiap permintaan web secara signifikan. API ini bersifat sinkron, dan tidak dapat diakses dari pekerja web. Seperti LocalStorage dan SessionStorage, cookie hanya terbatas pada string.
File System Access API dirancang agar pengguna dapat membaca dan mengedit file di sistem file lokal mereka. Pengguna harus memberikan izin sebelum halaman dapat membaca atau menulis ke file lokal, 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 menyimpan kembali perubahan ke file tersebut.
File System API dan FileWriter API menyediakan metode untuk membaca dan menulis file ke sistem file yang di-sandbox. Meskipun bersifat asinkron, 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 mengizinkan 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 oleh origin hingga 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 berkurang secara signifikan menjadi maksimum sekitar 300 MB.
- Firefox mengizinkan browser menggunakan hingga 50% ruang disk kosong. Grup
eTLD+1 (misalnya,
example.com,www.example.com, danfoo.bar.example.com) dapat menggunakan hingga 2 GB. Anda dapat menggunakan StorageManager API untuk menentukan sisa ruang penyimpanan yang masih tersedia. - Safari (desktop dan seluler) tampaknya mengizinkan sekitar 1 GB. Jika batas tercapai, Safari akan meminta pengguna untuk menaikkan batas dalam penambahan 200 MB. Saya tidak dapat menemukan dokumentasi resmi tentang hal ini.
- Jika PWA 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, sepertinya tidak ada cara untuk meminta penyimpanan tambahan.
Sebelumnya, jika situs melampaui batas tertentu data yang disimpan, browser akan meminta pengguna untuk memberikan izin menggunakan lebih banyak data. Misalnya, jika asal 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 dialokasikan. Pengecualiannya tampaknya adalah Safari, yang meminta izin untuk menambah kuota yang dialokasikan saat kuota penyimpanan terlampaui. Jika suatu origin mencoba menggunakan lebih dari kuota yang dialokasikan, 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. API ini melaporkan total jumlah byte yang digunakan oleh IndexedDB dan Cache API, serta memungkinkan untuk menghitung 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 melebihi kuota (lihat di bawah). Dalam beberapa kasus, kuota yang tersedia dapat melebihi jumlah penyimpanan sebenarnya yang tersedia.
Periksa
Selama pengembangan, Anda dapat menggunakan DevTools browser untuk memeriksa berbagai jenis penyimpanan, dan menghapus semua data yang tersimpan.
Fitur baru 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 Anda dalam skenario ketersediaan disk rendah. Buka Aplikasi, lalu Penyimpanan, aktifkan kotak centang Simulasikan kuota penyimpanan kustom, lalu masukkan angka yang valid untuk mensimulasikan kuota penyimpanan.
Saat mengerjakan panduan ini, saya menulis alat sederhana untuk berupaya menggunakan penyimpanan sebanyak mungkin dengan cepat. Cara ini adalah cara cepat untuk bereksperimen dengan berbagai mekanisme penyimpanan, dan melihat apa yang terjadi saat Anda menggunakan semua kuota.
Bagaimana cara menangani jika melebihi kuota?
Apa yang harus Anda lakukan jika Anda melebihi kuota? Yang terpenting, Anda harus selalu menangkap dan menangani error penulisan, baik itu QuotaExceededError maupun yang lainnya. Kemudian, bergantung pada desain aplikasi Anda, putuskan cara menanganinya.
Misalnya, hapus konten yang sudah lama tidak diakses, hapus
data berdasarkan ukuran, atau berikan cara bagi pengguna untuk memilih apa yang ingin mereka hapus.
IndexedDB dan Cache API menampilkan DOMError bernama QuotaExceededError saat Anda telah melampaui kuota yang tersedia.
IndexedDB
Jika asal telah melampaui kuotanya, upaya untuk menulis ke IndexedDB akan gagal. Handler onabort() transaksi akan dipanggil, meneruskan peristiwa.
Peristiwa ini 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 asal 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 dibersihkan oleh browser tanpa mengganggu pengguna, tetapi kurang tahan lama untuk data jangka panjang atau penting. Penyimpanan persisten tidak otomatis dikosongkan saat penyimpanan hampir penuh. Pengguna harus menghapus 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 atas pertimbangannya sendiri, misalnya, saat penyimpanan perangkat hampir penuh.
Kebijakan penghapusan untuk upaya terbaik adalah:
- Browser berbasis Chromium akan mulai menghapus data saat browser kehabisan ruang, dengan menghapus semua data situs dari asal 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 penuh, menghapus semua data situs dari asal yang paling jarang digunakan terlebih dahulu, lalu berikutnya, hingga browser tidak lagi melebihi batas.
- Sebelumnya, Safari 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 yang dapat ditulis skrip, termasuk IndexedDB, pendaftaran pekerja layanan, dan Cache API. Artinya, Safari akan mengeluarkan 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 artikel Full Third-Party Cookie Blocking and More di blog WebKit untuk mengetahui detail selengkapnya.
Bucket penyimpanan
Ide inti dari 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 menyulitkan untuk menyimpan data dengan kompleksitas rendah. Tidak seperti kebanyakan API berbasis promise modern, API ini berbasis peristiwa. Wrapper Promise seperti idb untuk IndexedDB menyembunyikan beberapa fitur canggih, tetapi yang lebih penting, menyembunyikan mekanisme kompleks (misalnya, transaksi, pembuatan versi skema) yang disertakan dengan library IndexedDB.
Bonus: SQLite Wasm
Setelah Web SQL dihentikan penggunaannya 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 Origin Private File System untuk mengetahui detail cara menggunakannya.
Kesimpulan
Tidak ada lagi batasan penyimpanan dan meminta pengguna untuk menyimpan lebih banyak data. Situs dapat menyimpan semua resource dan data yang dibutuhkan untuk berjalan secara efektif. Dengan menggunakan StorageManager API, Anda dapat menentukan jumlah penyimpanan yang tersedia untuk Anda, dan jumlah yang telah Anda gunakan. Dengan penyimpanan persisten, kecuali 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 bernama Browser Storage Abuser yang berguna dalam memvalidasi perilaku saat ini. Anda dapat menyimpan data sebanyak mungkin dan melihat batas penyimpanan di browser. Terima kasih kepada François Beaufort yang telah menyelidiki Safari untuk mengetahui batas penyimpanannya dan kepada Thomas Steiner yang telah menambahkan informasi tentang sistem file pribadi origin, bucket penyimpanan, SQLite Wasm, dan pembaruan konten secara keseluruhan pada tahun 2024.