Çevrimdışı veriler

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:

  1. cookbook adlı yeni bir IndexedDB veritabanı oluşturmak için openDB 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.
  2. upgrade() geri çağırma işlevi içeren bir ilk kullanıma hazırlama nesnesi openDB()'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. Genellikle upgrade() 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çin break ifadeleri içermeyen bir switch 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:

IndexedDB içeriklerini gösteren Safari ve Chrome.

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:

  1. mode readwrite olarak ayarlanmışken bir işlem başlatın.
  2. Veri ekleyeceğiniz nesne deposunu alın.
  3. 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 yerine put() 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:

  1. 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.
  2. İlgili işlemden objectStore()'ü arayın. Nesne mağazası adını belirttiğinizden emin olun.
  3. 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.

Uygulama, Depolama Alanını Temizle bölümündeki Chrome Geliştirici Araçları

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.

Mozilla Firefox'ta kullanıcıdan depolama alanı sürekliliği izni isteniyor.

API Tarayıcı desteği

Web Depolama

Browser Support

  • Chrome: 4.
  • Edge: 12.
  • Firefox: 3.5.
  • Safari: 4.

Source

Dosya Sistemi Erişimi

Browser Support

  • Chrome: 86.
  • Edge: 86.
  • Firefox: 111.
  • Safari: 15.2.

Source

Depolama Yöneticisi

Browser Support

  • Chrome: 55.
  • Edge: 79.
  • Firefox: 57.
  • Safari: 15.2.

Source

Kaynaklar