Sağlam bir çevrimdışı deneyim oluşturmak için PWA'nızın depolama alanı yönetimi yapması gerekir. Önbelleğe alma bölümünde, önbelleğe alma depolama alanının cihaza veri kaydetme seçeneklerinden biri olduğunu öğrendiniz. Bu bölümde, veri kalıcılığı, sınırlar ve mevcut araçlar da dahil olmak üzere çevrimdışı verileri nasıl yöneteceğinizi göstereceğiz.
Depolama
Depolama alanı yalnızca dosya ve öğelerden oluşmaz, diğer veri türlerini de içerebilir. PWA'ları destekleyen tüm tarayıcılarda cihaz üzerinde depolama için aşağıdaki API'ler kullanılabilir:
- IndexedDB: Yapılandırılmış veriler ve blob'lar (ikili veriler) için NoSQL nesne depolama seçeneği.
- WebStorage: Yerel depolama veya oturum depolamasını kullanarak anahtar/değer dize çiftlerini depolama yöntemidir. Hizmet çalışanı bağlamında kullanılamaz. Bu API senkronize olduğundan karmaşık veri depolama için önerilmez.
- Önbellek Depolama Alanı: Önbelleğe Alma modülünde açıklandığı gibi.
Desteklenen platformlarda Storage Manager API ile tüm cihaz depolama alanlarını yönetebilirsiniz. Cache Storage API ve IndexedDB, PWA'lar için kalıcı depolamaya eşzamansız erişim sağlar ve ana iş parçacığı, web çalışanları ve hizmet çalışanlarından erişilebilir. Her ikisi de ağ kararsız olduğunda veya olmadığında PWA'ların güvenilir bir şekilde çalışmasını sağlamada önemli bir rol oynar. Peki bu yöntemleri ne zaman kullanmalısınız?
HTML, CSS, JavaScript, resimler, videolar ve ses gibi ağ kaynakları (URL üzerinden isteyerek eriştiğiniz öğeler) için Cache Storage API'yi kullanın.
Yapılandırılmış verileri depolamak için IndexedDB'i kullanın. NoSQL benzeri bir şekilde aranabilir veya birleştirilebilir olması gereken veriler ya da bir URL isteğiyle mutlaka eşleşmeyen kullanıcıya özel veriler gibi diğer veriler buna dahildir. IndexedDB'in tam metin arama için tasarlanmadığını unutmayın.
IndexedDB
IndexedDB'yi kullanmak için önce bir veritabanı açın. Mevcut bir veritabanı yoksa yeni bir veritabanı oluşturulur.
IndexedDB bir eşzamansız API'dir ancak Promise döndürmek yerine bir geri çağırma işlevi alır. Aşağıdaki örnekte, Jake Archibald'ın IndexedDB için küçük bir Promise sarmalayıcısı olan idb kitaplığı kullanılmaktadır. IndexedDB'i kullanmak için yardımcı kitaplıklar gerekli değildir ancak Promise söz dizimini kullanmak istiyorsanız idb
kitaplığı bir seçenektir.
Aşağıdaki örnekte, yemek tariflerini barındıracak bir veritabanı oluşturulmaktadır.
Veritabanı oluşturma ve açma
Bir veritabanını açmak için:
cookbook
adlı yeni bir IndexedDB veritabanı oluşturmak içinopenDB
işlevini kullanın. IndexedDB veritabanları sürümlere sahip olduğundan, veritabanı yapısında değişiklik yaptığınızda sürüm numarasını artırmanız gerekir. İkinci parametre, veritabanı sürümüdür. Örnekte 1 olarak ayarlanmıştır.upgrade()
geri çağırma işlevi içeren bir ilk kullanıma hazırlama nesnesiopenDB()
'a iletilir. Geri çağırma işlevi, veritabanı ilk kez yüklendiğinde veya yeni bir sürüme yükseltildiğinde çağrılır. İşlemlerin gerçekleşebileceği tek yer bu işlevdir. İşlemler arasında yeni nesne depoları (IndexedDB'in verileri düzenlemek için kullandığı yapılar) veya dizinler (aramak istediğiniz) oluşturma yer alabilir. Veri taşıma işlemi de burada gerçekleşir. Genellikleupgrade()
işlevi, veritabanının eski sürümüne bağlı olarak her adımın sırayla gerçekleşmesine izin vermek içinbreak
ifadeleri içermeyen birswitch
ifadesi içerir.
import { openDB } from 'idb';
async function createDB() {
// Using https://github.com/jakearchibald/idb
const db = await openDB('cookbook', 1, {
upgrade(db, oldVersion, newVersion, transaction) {
// Switch over the oldVersion, *without breaks*, to allow the database to be incrementally upgraded.
switch(oldVersion) {
case 0:
// Placeholder to execute when database is created (oldVersion is 0)
case 1:
// Create a store of objects
const store = db.createObjectStore('recipes', {
// The `id` property of the object will be the key, and be incremented automatically
autoIncrement: true,
keyPath: 'id'
});
// Create an index called `name` based on the `type` property of objects in the store
store.createIndex('type', 'type');
}
}
});
}
Örnekte, cookbook
veritabanı içinde recipes
adlı bir nesne mağazası oluşturulur. Bu mağazada, id
mülkü mağazanın dizin anahtarı olarak ayarlanır ve type
mülküne göre type
adlı başka bir dizin oluşturulur.
Yeni oluşturulan nesne deposuna göz atalım. Nesne deposuna tarifler ekledikten ve Chromium tabanlı tarayıcılarda DevTools'u veya Safari'de Web Denetleyici'yi açtıktan sonra şunu görmeyi bekleyebilirsiniz:
Veri ekleme
IndexedDB işlem kullanır. İşlemler, işlemleri bir araya getirerek bir birim olarak gerçekleşmelerini sağlar. Bu işlemler, veritabanının her zaman tutarlı bir durumda olmasını sağlar. Ayrıca, uygulamanızın birden fazla kopyası çalışıyorsa aynı verilere aynı anda yazılmasını önlemek için de kilitleme işlemleri önemlidir. Veri eklemek için:
mode
readwrite
olarak ayarlanmışken bir işlem başlatın.- Veri ekleyeceğiniz nesne deposunu alın.
- Kaydettiğiniz verileri
add()
'e gönderin. Yöntem, verileri sözlük biçiminde (anahtar/değer çiftleri olarak) alır ve nesne deposuna ekler. Sözlük, Yapılandırılmış Klonlama kullanılarak klonlanabilir olmalıdır. Mevcut bir nesneyi güncellemek isterseniz bunun yerineput()
yöntemini çağırırsınız.
İşlemler, işlem başarıyla tamamlandığında çözülen veya işlem hatasıyla reddedilen bir done
vaadi içerir.
IDB kitaplığı dokümanlarında açıklandığı gibi, veritabanına yazıyorsanız tx.done
, her şeyin veritabanına başarıyla bağlandığının işaretidir. Ancak işlemin başarısız olmasına neden olan hataları görebilmeniz için işlemleri tek tek beklemeniz faydalıdır.
// Using https://github.com/jakearchibald/idb
async function addData() {
const cookies = {
name: "Chocolate chips cookies",
type: "dessert",
cook_time_minutes: 25
};
const tx = await db.transaction('recipes', 'readwrite');
const store = tx.objectStore('recipes');
store.add(cookies);
await tx.done;
}
Eklediğiniz kurabiyeler, diğer tariflerle birlikte veritabanında yer alır. Kimlik, indexedDB tarafından otomatik olarak ayarlanır ve artırılır. Bu kodu iki kez çalıştırırsanız iki adet aynı çerez girişiniz olur.
Verileri alma
IndexedDB'den veri alma işlemini aşağıdaki şekilde yapabilirsiniz:
- Bir işlem başlatın ve nesne mağazasını veya mağazaları ve isteğe bağlı olarak işlem türünü belirtin.
- İlgili işlemden
objectStore()
'ü arayın. Nesne mağazası adını belirttiğinizden emin olun. - Almak istediğiniz anahtarı
get()
'e gönderin. Mağaza varsayılan olarak anahtarını dizin olarak kullanır.
// Using https://github.com/jakearchibald/idb
async function getData() {
const tx = await db.transaction('recipes', 'readonly')
const store = tx.objectStore('recipes');
// Because in our case the `id` is the key, we would
// have to know in advance the value of the id to
// retrieve the record
const value = await store.get([id]);
}
Depolama alanı yöneticisi
PWA'nızın depolama alanını nasıl yöneteceğinizi bilmek, özellikle ağ yanıtlarını doğru şekilde depolamak ve yayınlamak için önemlidir.
Depolama alanı, önbellek depolama, IndexedDB, web depolama ve hatta hizmet çalışanı dosyası ve bağımlılıkları dahil tüm depolama seçenekleri arasında paylaşılır.
Ancak kullanılabilir depolama alanı tarayıcılara göre değişir. Bu depolama alanı dolmaz. Siteler bazı tarayıcılarda megabayt hatta gigabaytlarca veri depolayabilir. Örneğin Chrome, tarayıcının toplam disk alanının% 80'ine kadarını kullanmasına izin verir ve tek bir kaynak, disk alanının tamamının% 60'ına kadarını kullanabilir. Storage API'yi destekleyen tarayıcılarda, uygulamanız için ne kadar depolama alanı kaldığını, kotasını ve kullanımını öğrenebilirsiniz.
Aşağıdaki örnekte, Storage API kullanılarak tahmini kota ve kullanım bilgisi alınır, ardından kullanılan yüzde ve kalan bayt sayısı hesaplanır. navigator.storage
işlevinin StorageManager
örneği döndürdüğünü unutmayın. Ayrı bir Storage
arayüzü vardır ve bu iki arayüzü birbirine karıştırmak kolaydır.
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.`);
}
Chromium DevTools'da, Uygulama sekmesindeki Depolama bölümünü açarak sitenizin kotasını ve ne kadar depolama alanının kullanıldığını, kullananlara göre ayrılmış şekilde görebilirsiniz.
Firefox ve Safari, mevcut kaynağın tüm depolama alanı kotasını ve kullanımını gösteren bir özet ekranı sunmaz.
Veri kalıcılığı
Etkinlik olmaması veya depolama alanı baskısı nedeniyle otomatik veri kaldırma işlemini önlemek için uyumlu platformlarda tarayıcıdan kalıcı depolama alanı isteyebilirsiniz. İzin verilirse tarayıcı hiçbir zaman verileri depolama alanından kaldırmaz. Bu koruma, hizmet çalışanı kaydını, IndexedDB veritabanlarını ve önbellek depolama alanındaki dosyaları içerir. Kullanıcıların her zaman sorumlu olduğunu ve tarayıcı kalıcı depolama alanı izni vermiş olsa bile depolama alanını istedikleri zaman silebileceğini unutmayın.
Kalıcı depolama alanı isteğinde bulunmak için StorageManager.persist()
numaralı telefonu arayın. Önceki gibi, StorageManager
arayüzüne navigator.storage
mülkü üzerinden erişilir.
async function persistData() {
if (navigator.storage && navigator.storage.persist) {
const result = await navigator.storage.persist();
console.log(`Data persisted: ${result}`);
}
Ayrıca, StorageManager.persisted()
çağrısını yaparak mevcut kaynakta kalıcı depolama alanının zaten verilmiş olup olmadığını da kontrol edebilirsiniz. Firefox, kalıcı depolama alanını kullanmak için kullanıcıdan izin ister. Chromium tabanlı tarayıcılar, içeriğin kullanıcı için önemini belirlemek üzere bir heuristic'e göre kalıcılığı verir veya reddeder. Google Chrome için ölçütlerden biri, örneğin PWA yüklemesidir. Kullanıcı, işletim sistemine PWA için bir simge yüklediyse tarayıcı kalıcı depolama alanı izni verebilir.
API Tarayıcı desteği
Web Depolama
Dosya Sistemi Erişimi
Depolama Yöneticisi