Bir hizmet çalışanının hayatı

Yaşam döngüsünü anlamadan hizmet çalışanlarının ne yaptığını bilmek zordur. İç işleyişleri rastgele, hatta opak görünür. Diğer tarayıcı API'leri gibi Service Worker davranışlarının da iyi tanımlandığını, belirtildiğini, çevrimdışı uygulamaları mümkün kıldığını, kullanıcı deneyimini kesintiye uğratmadan güncellemeleri desteklediğini de unutmamak gerekir.

Workbox'a dalmadan önce, hizmet çalışanının yaşam döngüsünü anlamanız önemlidir. Böylece Workbox'ın işlevi mantıklıdır.

Terimleri tanımlama

Service Worker'ın yaşam döngüsüne girmeden önce, bu yaşam döngüsünün nasıl işlediğine dair bazı terimler tanımlamak faydalı olabilir.

Kontrol ve kapsam

Kontrol fikri, hizmet çalışanlarının nasıl çalıştığını anlamak açısından çok önemlidir. Service Worker tarafından kontrol ediliyor olarak tanımlanan sayfa, hizmet çalışanının kendi adına ağ isteklerine müdahale etmesine izin veren sayfadır. Hizmet çalışanı mevcut ve belirli bir kapsam dahilinde sayfa için çalışabilir.

Kapsam

Bir hizmet çalışanının kapsamı, web sunucusundaki konumuna göre belirlenir. Bir hizmet çalışanı, /subdir/index.html konumundaki bir sayfada çalışıyorsa ve /subdir/sw.js alanında bulunuyorsa hizmet çalışanının kapsamı /subdir/ olur. Kapsam kavramını uygulamada görmek için aşağıdaki örneği inceleyin:

  1. https://service-worker-scope-viewer.glitch.me/subdir/index.html adresine gidin. Sayfayı hiçbir hizmet çalışanının kontrol etmediğini belirten bir mesaj görünür. Ancak bu sayfa https://service-worker-scope-viewer.glitch.me/subdir/sw.js kaynağından bir hizmet çalışanı kaydeder.
  2. Sayfayı tekrar yükleyin. Service Worker kaydedildiği ve artık etkin olduğu için sayfayı kontrol etmektedir. Hizmet çalışanının kapsamını, mevcut durumunu ve URL'sini içeren bir form gösterilir. Not: Sayfanın yeniden yüklenmesinin kapsamla ilgisi yoktur. Bu durum, daha sonra açıklanacak olan hizmet çalışanı yaşam döngüsüyle ilgilidir.
  3. Şimdi https://service-worker-scope-viewer.glitch.me/index.html adresine gidin. Bir hizmet çalışanı bu kaynakta kayıtlı olsa da hâlâ mevcut hizmet çalışanı olmadığını belirten bir mesaj vardır. Bunun nedeni, bu sayfanın kayıtlı hizmet çalışanının kapsamında olmamasıdır.

Kapsam, hizmet çalışanının kontrol ettiği sayfaları sınırlar. Bu örnekte, /subdir/sw.js öğesinden yüklenen hizmet çalışanı yalnızca /subdir/ alanında veya alt ağacında bulunan sayfaları kontrol edebilir.

Kapsam oluşturma varsayılan olarak yukarıda açıklanmıştır ancak izin verilen maksimum kapsam, Service-Worker-Allowed yanıt başlığı ayarlanarak ve register yöntemine bir scope seçeneği geçirilerek geçersiz kılınabilir.

Service Worker kapsamını bir kaynağın alt kümesiyle sınırlamak için geçerli bir neden yoksa web sunucusunun kök dizininden hizmet çalışanı yükleyerek kapsamı mümkün olduğunca geniş tutun ve Service-Worker-Allowed üst bilgisini endişelenmeyin. Bu yöntem herkes için çok daha kolay.

Müşteri

Bir hizmet çalışanının bir sayfayı kontrol ettiği dendiğinde aslında bir istemciyi kontrol etmek anlamına gelir. İstemci, URL'si söz konusu hizmet çalışanının kapsamına giren tüm açık sayfalardır. Daha ayrıntılı olarak belirtmek gerekirse, bunlar WindowClient örnekleridir.

Yeni bir hizmet çalışanının yaşam döngüsü

Service Worker'ın bir sayfayı kontrol edebilmesi için deyim yerindeyse öncelikle sayfanın var olması gerekir. Etkin bir hizmet çalışanı olmayan bir web sitesine yepyeni bir hizmet çalışanı dağıtıldığında ne olacağıyla başlayalım.

Kayıt

Kayıt, hizmet çalışanı yaşam döngüsünün ilk adımıdır:

<!-- In index.html, for example: -->
<script>
  // Don't register the service worker
  // until the page has fully loaded
  window.addEventListener('load', () => {
    // Is service worker available?
    if ('serviceWorker' in navigator) {
      navigator.serviceWorker.register('/sw.js').then(() => {
        console.log('Service worker registered!');
      }).catch((error) => {
        console.warn('Error registering service worker:');
        console.warn(error);
      });
    }
  });
</script>

Bu kod ana iş parçacığında çalışır ve aşağıdakileri yapar:

  1. Kullanıcının bir web sitesini ilk ziyareti kayıtlı bir hizmet çalışanı olmadan gerçekleştiğinden, bir hizmet çalışanı kaydetmeden önce sayfanın tamamen yüklenmesini bekleyin. Hizmet çalışanı herhangi bir öğeyi önbelleğe alırsa bu, bant genişliği çakışmasını önler.
  2. Service Worker iyi bir şekilde desteklense de hızlı bir kontrol, desteklenmediği tarayıcılarda hatalardan kaçınmaya yardımcı olur.
  3. Sayfa tamamen yüklendiğinde ve hizmet çalışanı destekleniyorsa /sw.js öğesini kaydedin.

Anlaşılması gereken bazı önemli noktalar şunlardır:

  • Hizmet çalışanları yalnızca HTTPS veya localhost üzerinden kullanılabilir.
  • Service Worker'ın içeriğinde söz dizimi hataları varsa kayıt başarısız olur ve hizmet çalışanı silinir.
  • Hatırlatma: Service Worker'lar bir kapsam dahilinde çalışır. Burada kapsam, kök dizinden yüklendiği için kaynağın tamamıdır.
  • Kayıt başladığında hizmet çalışanı durumu 'installing' olarak ayarlanır.

Kayıt işlemi tamamlandıktan sonra yükleme işlemi başlar.

Döşeme

Bir hizmet çalışanı, kayıttan sonra install etkinliğini tetikler. install her hizmet çalışanı için yalnızca bir kez çağrılır ve güncellenene kadar tekrar etkinleşmez. install etkinliği için geri çağırma, çalışanın kapsamında addEventListener ile kaydedilebilir:

// /sw.js
self.addEventListener('install', (event) => {
  const cacheKey = 'MyFancyCacheName_v1';

  event.waitUntil(caches.open(cacheKey).then((cache) => {
    // Add all the assets in the array to the 'MyFancyCacheName_v1'
    // `Cache` instance for later use.
    return cache.addAll([
      '/css/global.bc7b80b7.css',
      '/css/home.fe5d0b23.css',
      '/js/home.d3cc4ba4.js',
      '/js/jquery.43ca4933.js'
    ]);
  }));
});

Bu işlem, yeni bir Cache örneği oluşturur ve öğeleri önbelleğe alır. Daha sonra önbelleğe alma hakkında konuşmak için birçok fırsatımız olacak. Bu yüzden şimdi event.waitUntil rolüne odaklanalım. event.waitUntil bir sözü kabul eder ve söz konusu taahhüdün yerine getirilmesini bekler. Bu örnekte, bu vaat iki eşzamansız işlem gerçekleştirir:

  1. 'MyFancyCache_v1' adında yeni bir Cache örneği oluşturur.
  2. Önbellek oluşturulduktan sonra bir dizi öğe URL'si, eşzamansız addAll yöntemi kullanılarak önbelleğe alınır.

event.waitUntil platformuna iletilen vaatler reddedilirse yükleme başarısız olur. Bu durumda hizmet çalışanı silinir.

Sözler resolve yükleme başarılı olur ve hizmet çalışanının durumu 'installed' olarak değişir ve ardından etkinleştirilir.

Yapılanlar

Kayıt ve yükleme başarılı olursa hizmet çalışanı etkinleşir ve durumu 'activating' olur. Hizmet çalışanının activate etkinliğindeki etkinleştirme sırasında iş yapılabilir. Bu olaydaki tipik bir görev eski önbellekleri ayıklamaktır ancak yeni bir hizmet çalışanı için bu şu an için geçerli değildir ve Service Worker güncellemelerinden bahsedildiğinde bu konu genişletilecektir.

Yeni hizmet çalışanları için activate, install başarılı olduktan hemen sonra etkinleşir. Etkinleştirme tamamlandığında hizmet çalışanının durumu 'activated' olur. Varsayılan olarak, yeni hizmet çalışanı bir sonraki gezinmeye veya sayfa yenilenene kadar sayfayı kontrol etmeye başlamayacaktır.

Hizmet çalışanı güncellemelerini işleme

İlk Service Worker dağıtıldıktan sonra muhtemelen bunun daha sonra güncellenmesi gerekir. Örneğin, istek işleme veya önbelleğe alma mantığında değişiklik olursa güncelleme gerekebilir.

Güncellemeler ne zaman yapılır?

Tarayıcılar, şu durumlarda hizmet çalışanı güncellemeleri olup olmadığını kontrol eder:

Güncellemeler nasıl yapılır?

Tarayıcının bir hizmet çalışanını ne zaman güncellediğini bilmek önemlidir ancak "nasıl" sorusunun cevabı da önemlidir. Bir hizmet çalışanının URL'sinin veya kapsamının değişmediği varsayıldığında, şu anda yüklü bir hizmet çalışanının sürümü yalnızca içeriği değiştiyse yeni bir sürüme güncellenir.

Tarayıcılar, değişiklikleri birkaç şekilde algılar:

  • Komut dosyalarında, varsa importScripts tarafından istenen bayt ve bayt değişiklikleri.
  • Hizmet çalışanının üst düzey kodunda yapılan ve tarayıcının oluşturduğu parmak izini etkileyen değişiklikler.

Tarayıcı burada çok iş yapıyor. Tarayıcının, Service Worker'ın içeriklerindeki değişiklikleri güvenilir bir şekilde tespit etmesi için gereken tüm özelliklere sahip olduğundan emin olmak amacıyla, HTTP önbelleğine verileri tutmasını söylemeyin ve dosya adını değiştirmeyin. Tarayıcı, hizmet çalışanının kapsamında yeni bir sayfaya gitme olduğunda otomatik olarak güncelleme kontrolleri gerçekleştirir.

Güncelleme kontrollerini manuel olarak tetikleme

Güncellemeler söz konusu olduğunda, kayıt mantığı genel olarak değişmeyecektir. Bununla birlikte, bir web sitesindeki oturumların süresi uzun olabilir. Uygulama yaşam döngüsünün başında tek bir gezinme isteğiyle karşılaştığı için bu durum, gezinme isteklerinin nadir olduğu tek sayfalık uygulamalarda gerçekleşebilir. Bu tür durumlarda, ana ileti dizisinde manuel güncelleme tetiklenebilir:

navigator.serviceWorker.ready.then((registration) => {
  registration.update();
});

Geleneksel web sitelerinde veya kullanıcı oturumlarının uzun sürmediği durumlarda, manuel güncellemelerin tetiklenmesi muhtemelen gerekli değildir.

Döşeme

Statik öğeler oluşturmak için bir paketleyici kullanırken bu öğelerin adlarında framework.3defa9d2.js gibi karmalar bulunur. Bu öğelerden bazılarının daha sonra çevrimdışı erişim için önbelleğe alındığını varsayalım. Bu durumda, güncellenen öğelerin önbelleğe alınması için Service Worker güncellemesi yapılması gerekir.

self.addEventListener('install', (event) => {
  const cacheKey = 'MyFancyCacheName_v2';

  event.waitUntil(caches.open(cacheKey).then((cache) => {
    // Add all the assets in the array to the 'MyFancyCacheName_v2'
    // `Cache` instance for later use.
    return cache.addAll([
      '/css/global.ced4aef2.css',
      '/css/home.cbe409ad.css',
      '/js/home.109defa4.js',
      '/js/jquery.38caf32d.js'
    ]);
  }));
});

Önceki install etkinlik örneğinden iki şey farklıdır:

  1. 'MyFancyCacheName_v2' anahtarına sahip yeni bir Cache örneği oluşturulur.
  2. Önbelleğe alınan öğe adları değişti.

Bir öncekinin yanı sıra güncellenmiş bir hizmet çalışanının da yüklendiğini unutmayın. Bu, eski Service Worker'ın açık sayfaların kontrolünü hâlâ elinde olduğu ve yükleme sonrasında, yeni hizmet etkinleştirilene kadar bekleme durumuna gireceği anlamına gelir.

Varsayılan olarak, hiçbir istemci eskisi tarafından denetlenmediğinde yeni bir Service Worker etkinleştirilir. Bu durum, ilgili web sitesine ait tüm açık sekmeler kapatıldığında meydana gelir.

Yapılanlar

Güncellenmiş bir hizmet çalışanı yüklenip bekleme aşaması sona erdiğinde etkinleşir ve eski hizmet çalışanı silinir. Güncellenen bir hizmet çalışanının activate etkinliğinde gerçekleştirilen yaygın görev, eski önbellekleri ayıklamaktır. caches.keys içeren tüm açık Cache örneklerinin anahtarlarını alarak ve caches.delete ile tanımlı bir izin verilenler listesinde olmayan önbellekleri silerek eski önbellekleri kaldırın:

self.addEventListener('activate', (event) => {
  // Specify allowed cache keys
  const cacheAllowList = ['MyFancyCacheName_v2'];

  // Get all the currently active `Cache` instances.
  event.waitUntil(caches.keys().then((keys) => {
    // Delete all caches that aren't in the allow list:
    return Promise.all(keys.map((key) => {
      if (!cacheAllowList.includes(key)) {
        return caches.delete(key);
      }
    }));
  }));
});

Eski önbellekler kendilerini düzeltmez. Bu işlemi kendimiz yapmalıyız yoksa depolama alanı kotalarını aşma riskiyle karşı karşıya kalabiliriz. İlk hizmet çalışanındaki 'MyFancyCacheName_v1' güncel olmadığından, önbelleğe alınan izin verilenler listesi 'MyFancyCacheName_v2' alanını belirtecek şekilde güncellenir. Bu da farklı bir ada sahip önbellekleri siler.

activate etkinliği, eski önbellek kaldırıldıktan sonra sona erer. Bu noktada yeni hizmet çalışanı sayfanın kontrolünü ele geçirir ve son olarak eskisinin yerini alır.

Yaşam döngüsü hiç bitmiyor

Workbox'ın hizmet çalışanı dağıtımı ve güncellemeleri için kullanılması veya doğrudan Service Worker API kullanılması fark etmeksizin, hizmet çalışanı yaşam döngüsünü anlamak için ödeme yaparsınız. Bu anlayış göz önüne alındığında Service Worker'ların davranışları gizemli olmaktan çok daha mantıklı bir şekilde görülebilir.

Bu konuyu daha ayrıntılı şekilde incelemek isteyenler Jake Archibald'ın bu makalesini incelemelidir. Hizmet yaşam döngüsündeki bütün dansın nasıl geçtiği konusunda tonlarca nüans olsa da bu durum bilinebilir ve Workbox kullanıldığında bu bilgi çok daha başarılı olacaktır.