zorunluluk önbelleğe alma kılavuzu

Andrew Guan
Andrew Guan
Demián Renzulli
Demián Renzulli

Bazı web sitelerinin, sonuç hakkında bilgilendirilmeye gerek kalmadan Service Worker'la iletişim kurması gerekebilir. Bazı örnekler:

  • Sayfa, önceden getirmek için hizmet çalışanına bir URL listesi gönderir. Böylece kullanıcı bir bağlantıyı tıkladığında, doküman veya sayfa alt kaynakları zaten önbellekte bulunur ve böylece sonraki gezinme çok daha hızlı hale gelir.
  • Sayfa, hizmet çalışanından en popüler makalelerden oluşan bir grubu alıp önbelleğe almasını ister. Böylece, söz konusu makaleler çevrimdışı amaçlarla kullanılabilir.

Bu tür kritik olmayan görevlerin hizmet çalışanına devredilmesi, ana iş parçacığının kullanıcı etkileşimlerine yanıt verme gibi daha acil görevleri daha iyi şekilde ele alınması için serbest kalma avantajını sunar.

Kaynakların Service Worker'da önbelleğe alınmasını isteyen sayfanın şeması.

Bu kılavuzda, standart tarayıcı API'lerini ve Workbox kitaplığını kullanarak sayfadan Service Worker'a tek yönlü bir iletişim tekniğini nasıl uygulayacağınızı inceleyeceğiz. Bu tür kullanım alanlarını zorunlu önbelleğe alma olarak adlandıracağız.

Üretim örneği

1-800-Flowers.com, ürün ayrıntıları sayfalarına daha sonra gitmeyi hızlandırmak amacıyla kategori sayfalarındaki en iyi öğeleri önceden getirmek için postMessage() aracılığıyla Service Worker'lar ile zorunlu önbelleğe alma (önceden getirme) yöntemini uyguladı.

1-800 Flowers logosu.

Hangi öğelerin önceden getirileceğine karar vermek için karma bir yaklaşım kullanırlar:

  • Sayfa yüklenirken Servicer çalışanı en iyi 9 öğe için JSON verilerini almasını ve sonuçta elde edilen yanıt nesnelerini önbelleğe almasını ister.
  • Kalan öğeler için mouseover etkinliğini dinlerler. Böylece kullanıcı, imleci bir öğenin üzerine getirdiğinde "isteğe bağlı" kaynak için bir getirme işlemini tetikleyebilir.

JSON yanıtlarını depolamak için Cache API'yi kullanırlar:

1-800 Flowers logosu.
1-800Flowers.com'daki ürün listeleme sayfalarından JSON ürün verilerini önceden getirme.

Kullanıcı bir öğeyi tıkladığında, bu öğeyle ilişkili JSON verileri ağa gitmeye gerek kalmadan önbellekten alınabilir. Böylece gezinme daha hızlı hale gelir.

Workbox'ı kullanma

Workbox, pencere bağlamında çalışması amaçlanan bir dizi modül olan workbox-window paketi aracılığıyla Service Worker'a mesaj göndermenin kolay bir yolunu sunar. Service Worker'da çalışan diğer Workbox paketlerini tamamlayıcı niteliktedir.

Sayfayı hizmet çalışanıyla iletişim kurmak için önce kayıtlı Service Worker'a bir Workbox nesne referansı alın:

const wb = new Workbox('/sw.js');
wb.register();

Ardından kaydı almak, etkinleştirmeyi kontrol etmek veya temel iletişim API'sını düşünmek zorunda kalmadan mesajı doğrudan bildirimli bir şekilde gönderebilirsiniz:

wb.messageSW({"type": "PREFETCH", "payload": {"urls": ["/data1.json", "data2.json"]}}); });

Service Worker, bu mesajları dinlemek için bir message işleyici uygular. İsteğe bağlı olarak yanıt döndürebilir ancak aşağıdaki gibi durumlarda gerekli değildir:

self.addEventListener('message', (event) => {
  if (event.data && event.data.type === 'PREFETCH') {
    // do something
  }
});

Tarayıcı API'lerini kullanma

Workbox kitaplığı ihtiyaçlarınız için yeterli değilse tarayıcı API'lerini kullanarak hizmet çalışanı iletişimine pencereyi nasıl uygulayabileceğiniz aşağıda açıklanmıştır.

postMessage API, sayfadan Service Worker'a tek yönlü bir iletişim mekanizması oluşturmak için kullanılabilir.

Sayfa, Service Worker arayüzünde postMessage() çağrısı yapar:

navigator.serviceWorker.controller.postMessage({
  type: 'MSG_ID',
  payload: 'some data to perform the task',
});

Service Worker, bu mesajları dinlemek için bir message işleyici uygular.

self.addEventListener('message', (event) => {
  if (event.data && event.data.type === MSG_ID) {
    // do something
  }
});

{type : 'MSG_ID'} özelliği kesinlikle gerekli değildir ancak sayfanın hizmet çalışanına farklı türde talimatlar göndermesine (yani "önceden getirme" ve "depolama alanını temizlemek" için) izin vermenin bir yoludur. Service Worker, bu işarete göre farklı yürütme yollarına dalabilir.

İşlem başarılı olduysa kullanıcı bundan yararlanabilir, ancak başarılı olmazsa ana kullanıcı akışında değişiklik olmaz. Örneğin, 1-800-Flowers.com önbelleğe almayı denediğinde sayfanın hizmet çalışanının başarılı olup olmadığını bilmesi gerekmez. Bu durumda, kullanıcı daha hızlı bir gezinme deneyiminin keyfini çıkaracaktır. Bağlanmazsa sayfanın yine de yeni sayfaya gitmesi gerekir. Biraz daha uzun sürecek.

Basit bir önceden getirme örneği

Zorunlu önbelleğe almanın en yaygın uygulamalarından biri, önceden getirme, yani gezinmeyi hızlandırmak için kullanıcı gitmeden önce belirli bir URL'nin kaynaklarını getirmektir.

Sitelerde önceden getirme uygulamasının farklı yolları vardır:

Belgeleri veya belirli öğeleri (JS, CSS vb.) önceden getirme gibi görece basit olan önceden getirme senaryoları için bu teknikler en iyi yaklaşımdır.

Ek mantık gerekirse (örneğin, dahili URL'lerini getirmek için önceden getirme kaynağını (bir JSON dosyası veya sayfası) ayrıştırmak) bu görevin tamamını Service Worker'a devretmek daha uygun olur.

Bu tür işlemleri Service Worker'a devretmek şu avantajlara sahiptir:

  • Getirme ve getirme sonrası işlemenin (daha sonra açıklanacak olan) ağır yükünü ikincil bir iş parçacığına boşaltma. Bunu yaparak ana iş parçacığını, kullanıcı etkileşimlerine yanıt verme gibi daha önemli görevleri yerine getirmesi için serbest bırakır.
  • Birden çok istemcinin (ör. sekmeler) ortak bir işlevi yeniden kullanmasına, hatta ana iş parçacığını engellemeden aynı anda hizmetin çağrılmasına izin verme.

Ürün ayrıntısı sayfalarını önceden getir

Önce Service Worker arayüzünde postMessage() kullanın ve önbelleğe alınacak bir URL dizisi iletin:

navigator.serviceWorker.controller.postMessage({
  type: 'PREFETCH',
  payload: {
    urls: [
      'www.exmaple.com/apis/data_1.json',
      'www.exmaple.com/apis/data_2.json',
    ],
  },
});

Service Worker'da, etkin bir sekmede gönderilen mesajları engellemek ve işlemek için bir message işleyici uygulayın:

addEventListener('message', (event) => {
  let data = event.data;
  if (data && data.type === 'PREFETCH') {
    let urls = data.payload.urls;
    for (let i in urls) {
      fetchAsync(urls[i]);
    }
  }
});

Önceki kodda, URL dizisini yinelemek ve her biri için bir getirme isteği göndermek üzere fetchAsync() adlı küçük bir yardımcı işlevi tanıttık:

async function fetchAsync(url) {
  // await response of fetch call
  let prefetched = await fetch(url);
  // (optionally) cache resources in the service worker storage
}

Yanıt alındığında, kaynağın önbelleğe alma üst bilgilerini kullanabilirsiniz. Yine de, ürün ayrıntıları sayfalarında olduğu gibi birçok durumda kaynaklar önbelleğe alınmaz (yani, Cache-control üst bilgisi no-cache olur). Bu gibi durumlarda, getirilen kaynağı Service Worker önbelleğinde depolayarak bu davranışı geçersiz kılabilirsiniz. Bu, dosyanın çevrimdışı senaryolarda sunulmasına olanak tanıma avantajını da sunar.

JSON verilerinin ötesinde

JSON verileri bir sunucu uç noktasından getirildikten sonra genellikle bu birinci düzey verilerle ilişkili bir resim veya diğer uç nokta verileri gibi önceden getirilmeye değer diğer URL'leri de içerir.

Örneğimizde, döndürülen JSON verilerinin bir market alışverişi sitesinin bilgileri olduğunu varsayalım:

{
  "productName": "banana",
  "productPic": "https://cdn.example.com/product_images/banana.jpeg",
  "unitPrice": "1.99"
 }

Ürün listesini yinelemek üzere fetchAsync() kodunu değiştirin ve her biri için hero resmi önbelleğe alın:

async function fetchAsync(url, postProcess) {
  // await response of fetch call
  let prefetched = await fetch(url);

  //(optionally) cache resource in the service worker cache

  // carry out the post fetch process if supplied
  if (postProcess) {
    await postProcess(prefetched);
  }
}

async function postProcess(prefetched) {
  let productJson = await prefetched.json();
  if (productJson && productJson.product_pic) {
    fetchAsync(productJson.product_pic);
  }
}

404 gibi durumlar için bu kod etrafına bazı istisna işlemleri ekleyebilirsiniz. Ancak önceden getirme işlemi için bir Service Worker kullanmanın güzel yanı, sayfa ve ana iş parçacığıyla fazla ilgisi olmadan başarısız olabilmesidir. Ayrıca, önceden getirilen içeriğin sonradan işlenmesinde daha ayrıntılı bir mantığınız olabilir. Böylece, içeriği daha esnek hale getirebilir ve işlediği verilerle ayrıştırabilirsiniz. Sizi sınırlayan hiçbir şey yok.

Sonuç

Bu makalede, sayfa ile hizmet çalışanı arasında tek yönlü iletişimin yaygın bir kullanım alanını ele aldık: zorunlu önbelleğe alma. Bahsedilen örnekler yalnızca bu kalıbı kullanmanın bir yolunu göstermek için tasarlanmıştır ve aynı yaklaşım, çevrimdışı tüketim için en çok okunan makaleleri önbelleğe alma, yer işareti ekleme ve diğer kullanım alanları için de geçerli olabilir.

Sayfa ve hizmet çalışanı iletişimiyle ilgili daha fazla kalıp için şuraya göz atın:

  • Güncellemeleri yayınlama: Önemli güncellemeler hakkında bilgi vermek için hizmet çalışanının sayfaya çağrı yapması (ör. web uygulamasının yeni bir sürümü kullanılabilir).
  • İki yönlü iletişim: Bir hizmet çalışanına görev için yetki verme (ör. ağır bir indirme) ve sayfayı süreç hakkında bilgilendirme.