Tarayıcıda veri depolamak için birçok farklı seçenek vardır. İhtiyaçlarınıza en uygun olanı hangisi?
İnternet bağlantıları hareket halindeyken kesintili olabilir veya hiç olmayabilir. Bu nedenle, çevrimdışı destek ve güvenilir performans, progresif web uygulamalarında yaygın olarak görülen özelliklerdir. Mükemmel kablosuz ortamlarda bile önbelleğe alma ve diğer depolama tekniklerinin akıllıca kullanılması, kullanıcı deneyimini önemli ölçüde iyileştirebilir. Statik uygulama kaynaklarınızı (HTML, JavaScript, CSS, resimler vb.) ve verilerinizi (kullanıcı verileri, haber makaleleri vb.) önbelleğe almanın birkaç yolu vardır. Peki en iyi çözüm hangisi? Ne kadar veri depolayabilirsiniz? Bu pod'un çıkarılmasını nasıl önlersiniz?
Hangisini kullanmalıyım?
Kaynakları depolamak için genel bir öneri:
- Uygulamanızı yüklemek için gereken ağ kaynakları için Cache Storage API'yi (hizmet çalışanlarının bir parçası) kullanın.
- Dosya tabanlı içerikler için Origin Private File System (OPFS) kullanın.
- Diğer veriler için IndexedDB'yi (promises sarmalayıcısı ile) kullanın.
IndexedDB, OPFS ve Cache Storage API tüm modern tarayıcılarda desteklenir.
Eşzamansızdırlar ve ana iş parçacığını engellemezler (ancak OPFS'nin yalnızca web çalışanlarında kullanılabilen eşzamanlı bir varyantı da vardır). window nesnesinden, web çalışanlarından ve hizmet çalışanlarından erişilebilirler. Bu sayede, kodunuzun herhangi bir yerinde kullanılabilirler.
Peki ya diğer depolama mekanizmaları?
Tarayıcıda başka depolama mekanizmaları da vardır ancak bunların kullanımı sınırlıdır ve önemli performans sorunlarına neden olabilirler.
SessionStorage sekmeye özeldir ve sekmenin kullanım ömrüyle sınırlıdır. Oturuma özgü az miktarda bilgiyi (ör. IndexedDB anahtarı) depolamak için yararlı olabilir. Eşzamanlı olduğu ve ana iş parçacığını engelleyeceği için dikkatli kullanılmalıdır. Yaklaşık 5 MB ile sınırlıdır ve yalnızca dize içerebilir. Sekmeye özel olduğu için web çalışanları veya hizmet çalışanları tarafından erişilemez.
LocalStorage, eşzamanlı olduğu ve ana iş parçacığını engelleyeceği için kullanılmamalıdır. Yaklaşık 5 MB ile sınırlıdır ve yalnızca dize içerebilir. LocalStorage'a web çalışanlarından veya hizmet çalışanlarından erişilemez.
Çerezlerin kullanım alanları vardır ancak depolama için kullanılmamalıdır. Çerezler her HTTP isteğiyle birlikte gönderilir. Bu nedenle, az miktarda veriden fazlasını depolamak her web isteğinin boyutunu önemli ölçüde artırır. Bunlar eşzamanlıdır ve web çalışanları tarafından erişilemez. LocalStorage ve SessionStorage gibi çerezler de yalnızca dizelerle sınırlıdır.
File System Access API, kullanıcıların yerel dosya sistemlerindeki dosyaları okuyup düzenleyebilmeleri için tasarlanmıştır. Bir sayfanın herhangi bir yerel dosyayı okuyabilmesi veya dosyaya yazabilmesi için kullanıcının izin vermesi gerekir. Dosya tanıtıcısı IndexedDB'de önbelleğe alınmadığı sürece izinler oturumlar arasında kalıcı olmaz. Dosya Sistemi Erişimi API'si, bir dosyayı açmanız, değiştirmeniz ve ardından değişiklikleri dosyaya kaydetmeniz gereken düzenleyiciler gibi kullanım alanları için en uygun seçenektir.
File System API ve FileWriter API, korumalı alana alınmış bir dosya sistemine dosya okuma ve yazma yöntemleri sağlar. Eşzamansız olsa da yalnızca Chromium tabanlı tarayıcılarda kullanılabildiği için önerilmez.
Ne kadar veri depolayabilirim?
Kısacası çok fazla, en az birkaç yüz megabayt ve potansiyel olarak yüzlerce gigabayt veya daha fazla. Tarayıcı uygulamaları farklılık gösterir ancak kullanılabilir depolama alanı miktarı genellikle cihazdaki kullanılabilir depolama alanı miktarına bağlıdır.
- Chrome, tarayıcının toplam disk alanının %80'ini kullanmasına izin verir. Bir kaynak, toplam disk alanının %60'ına kadarını kullanabilir. Maksimum kullanılabilir kotayı belirlemek için StorageManager API'yi kullanabilirsiniz. Chromium tabanlı diğer tarayıcılar farklı olabilir.
- Gizli modda Chrome, bir kaynağın kullanabileceği depolama alanı miktarını toplam disk alanının yaklaşık %5'ine düşürür.
- Kullanıcı Chrome'da "Tüm pencereler kapatıldığında çerezleri ve site verilerini temizle" ayarını etkinleştirdiyse depolama alanı kotası önemli ölçüde azaltılarak maksimum yaklaşık 300 MB'a düşürülür.
- Firefox, tarayıcının boş disk alanının %50'sine kadarını kullanmasına izin verir. Bir eTLD+1 grubu (ör.
example.com,www.example.comvefoo.bar.example.com) en fazla 2 GB kullanabilir. Ne kadar alan kaldığını belirlemek için StorageManager API'yi kullanabilirsiniz. - Safari (hem masaüstü hem de mobil) yaklaşık 1 GB'a izin veriyor. Sınıra ulaşıldığında Safari, kullanıcıdan sınırı 200 MB'lık artışlarla yükseltmesini ister. Bu konuyla ilgili resmi bir belge bulamadım.
- Bir PWA, mobil Safari'de ana ekrana eklenirse yeni bir depolama alanı kapsayıcısı oluşturur ve PWA ile mobil Safari arasında hiçbir şey paylaşılmaz. Yüklü bir PWA için kotaya ulaşıldığında ek depolama alanı istemenin bir yolu yoktur.
Geçmişte, bir site belirli bir depolanan veri eşiğini aşarsa tarayıcı, kullanıcıdan daha fazla veri kullanma izni vermesini isterdi. Örneğin, kaynak 50 MB'tan fazla alan kullandıysa tarayıcı, kullanıcıdan 100 MB'a kadar depolama alanına izin vermesini ister, ardından 50 MB'lık artışlarla tekrar sorar.
Günümüzde çoğu modern tarayıcı, kullanıcıdan izin istemez ve sitelerin kendilerine ayrılan kotayı kullanmasına izin verir. Safari bu konuda bir istisna gibi görünüyor. Depolama alanı kotası aşıldığında istem göstererek ayrılan kotayı artırmak için izin istiyor. Bir kaynak, kendisine ayrılan kotadan fazlasını kullanmaya çalışırsa veri yazma girişimleri başarısız olur.
Ne kadar depolama alanı olduğunu nasıl kontrol edebilirim?
Birçok tarayıcıda, kaynağın kullanabileceği depolama alanı miktarını ve ne kadar depolama alanı kullandığını belirlemek için StorageManager API'yi kullanabilirsiniz. IndexedDB ve Cache API tarafından kullanılan toplam bayt sayısını bildirir ve kalan yaklaşık depolama alanını hesaplamayı mümkün kılar.
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.`);
}
Kota aşımı hatalarını yakalamanız gerekir (aşağıya bakın). Bazı durumlarda, kullanılabilir kota gerçekte kullanılabilir depolama alanı miktarını aşabilir.
İnceleme
Geliştirme sırasında, farklı depolama türlerini incelemek ve depolanan tüm verileri temizlemek için tarayıcınızın Geliştirici Araçları'nı kullanabilirsiniz.
Chrome 88'e, Depolama Alanı Bölmesi'nde sitenin depolama alanı kotasını geçersiz kılmanıza olanak tanıyan yeni bir özellik eklendi. Bu özellik, farklı cihazların simülasyonunu yapmanıza ve uygulamalarınızın davranışını düşük disk kullanılabilirliği senaryolarında test etmenize olanak tanır. Uygulama'ya, ardından Depolama Alanı'na gidin, Özel depolama alanı kotasını simüle et onay kutusunu işaretleyin ve depolama alanı kotasını simüle etmek için geçerli bir sayı girin.
Kota aşımı nasıl yönetilir?
Kotanızı aştığınızda ne yapmanız gerekir? En önemlisi, QuotaExceededError veya başka bir hata olsun, yazma hatalarını her zaman yakalayıp ele almanız gerekir. Ardından, uygulama tasarımınıza bağlı olarak bu durumu nasıl ele alacağınıza karar verin.
Örneğin, uzun süredir erişilmeyen içerikleri silebilir, boyuta göre verileri kaldırabilir veya kullanıcılara silmek istedikleri verileri seçme imkanı sunabilirsiniz.
Kullanılabilir kotayı aştığınızda hem IndexedDB hem de Cache API, DOMError adlı bir QuotaExceededError hatası verir.
IndexedDB
Kaynak, kotasını aşarsa IndexedDB'ye yazma girişimleri başarısız olur. İşlemin onabort() işleyicisi çağrılır ve bir etkinlik iletilir.
Etkinlik, hata özelliğinde bir DOMException içerir. name hatası kontrol edildiğinde QuotaExceededError döndürülür.
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
Kaynak, kotasını aşarsa Cache API'ye yazma girişimleri QuotaExceededError DOMException ile reddedilir.
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
}
}
Tahliye nasıl çalışır?
Web depolama alanı, "En İyi Sonuç" ve "Kalıcı" olmak üzere iki gruba ayrılır. En iyi çaba, depolama alanının kullanıcıyı kesintiye uğratmadan tarayıcı tarafından temizlenebileceği anlamına gelir ancak uzun vadeli veya kritik veriler için daha az dayanıklıdır. Depolama alanı azaldığında kalıcı depolama alanı otomatik olarak temizlenmez. Kullanıcının bu depolama alanını manuel olarak (tarayıcı ayarları üzerinden) temizlemesi gerekir.
Varsayılan olarak, bir sitenin verileri (IndexedDB, Cache API vb. dahil) en iyi çaba kategorisine girer. Bu, bir site kalıcı depolama alanı istemediği sürece tarayıcının, site verilerini kendi takdirine bağlı olarak (ör. cihaz depolama alanı azaldığında) silebileceği anlamına gelir.
En iyi çaba için çıkarma politikası şöyledir:
- Chromium tabanlı tarayıcılar, tarayıcıda yer kalmadığında verileri çıkarmaya başlar. Önce en eski kaynaktan başlayarak tüm site verilerini temizler ve tarayıcı artık sınırın altına düşene kadar bu işlemi sürdürür.
- Firefox, kullanılabilir disk alanı dolduğunda verileri silmeye başlar. Önce en eski kaynaktan başlayarak tüm site verilerini temizler ve tarayıcı artık sınırın altında kalana kadar bu işlemi sürdürür.
- Safari daha önce verileri silmiyordu ancak kısa süre önce tüm yazılabilir depolama alanları için yedi günlük yeni bir sınır uyguladı (aşağıya bakın).
iOS ve iPadOS 13.4 ve macOS'te Safari 13.1'den itibaren, IndexedDB, hizmet çalışanı kaydı ve Cache API dahil olmak üzere tüm komut dosyası yazılabilir depolama alanları için yedi günlük bir sınır vardır. Bu, kullanıcının siteyle etkileşimde bulunmaması durumunda Safari'nin yedi günlük Safari kullanımından sonra önbellekteki tüm içeriği kaldıracağı anlamına gelir. Bu çıkarma politikası, ana ekrana eklenmiş yüklü PWA'lar için geçerli değildir. Tüm ayrıntılar için WebKit blogundaki Full Third-Party Cookie Blocking and More (Üçüncü Taraf Çerezlerini Tamamen Engelleme ve Daha Fazlası) başlıklı makaleyi inceleyin.
Depolama paketleri
Storage Buckets API'nin temel fikri, sitelere birden fazla depolama alanı grubu oluşturma olanağı sağlamaktır. Tarayıcı, her bir grubu diğer gruplardan bağımsız olarak silmeyi seçebilir. Bu sayede geliştiriciler, en değerli verilerin silinmemesi için çıkarma önceliklendirmesini belirtebilir.
Bonus: IndexedDB için neden sarmalayıcı kullanmalısınız?
IndexedDB, kullanılmadan önce önemli bir kurulum gerektiren düşük seviyeli bir API'dir. Bu durum, özellikle düşük karmaşıklığa sahip verileri depolamak için zorlayıcı olabilir. Modern, Promise tabanlı API'lerin çoğunun aksine, etkinlik tabanlıdır. IndexedDB için idb gibi Promise sarmalayıcıları, güçlü özelliklerden bazılarını gizler ancak daha da önemlisi, IndexedDB kitaplığıyla birlikte gelen karmaşık mekanizmayı (ör. işlemler, şema sürümü oluşturma) gizler.
Bonus: SQLite Wasm
Web SQL'in desteği sonlandırılıp Chrome'dan kaldırıldıktan sonra Google, popüler SQLite veritabanının geliştiricileriyle birlikte çalışarak Web SQL'in yerine SQLite tabanlı bir alternatif sundu. Kullanımıyla ilgili ayrıntılar için Tarayıcıda Origin Private File System tarafından desteklenen SQLite Wasm başlıklı makaleyi okuyun.
Sonuç
Sınırlı depolama alanı ve kullanıcıdan daha fazla veri depolamasını isteme günleri geride kaldı. Siteler, çalışmak için ihtiyaç duydukları tüm kaynakları ve verileri etkili bir şekilde depolayabilir. StorageManager API'yi kullanarak ne kadar depolama alanınız olduğunu ve ne kadarını kullandığınızı belirleyebilirsiniz. Kalıcı depolama alanı sayesinde, kullanıcı kaldırmadığı sürece verileri silinmeye karşı koruyabilirsiniz.
Ek kaynaklar
Teşekkürler
Bu kılavuzu inceledikleri için Jarryd Goodman, Phil Walton, Eiji Kitamura, Daniel Murphy, Darwin Huang, Josh Bell, Marijn Kruisselbrink ve Victor Costan'a özel olarak teşekkür ederiz. Bu makalenin temel aldığı orijinal makaleleri yazan Eiji Kitamura, Addy Osmani ve Marc Cohen'e teşekkür ederiz. Eiji, mevcut davranışı doğrulamada yararlı olan Browser Storage Abuser adlı faydalı bir araç yazdı. Bu sayede, mümkün olduğunca fazla veri depolayabilir ve tarayıcınızdaki depolama alanı sınırlarını görebilirsiniz. Depolama alanı sınırlarını öğrenmek için Safari'yi inceleyen François Beaufort'a ve kaynak özel dosya sistemi, depolama alanı grupları, SQLite Wasm hakkında bilgi eklediği ve 2024'te genel bir içerik güncellemesi yaptığı için Thomas Steiner'a teşekkür ederiz.