Hizmet işçilerinin yaşam döngülerini anlamadan ne yaptıklarını bilmek zordur. İç işleyişleri şeffaf değil, hatta keyfi görünecektir. Diğer tüm tarayıcı API'leri gibi hizmet çalışanı davranışlarının iyi tanımlandığını, belirtildiğini ve çevrimdışı uygulamaları mümkün kıldığını, ayrıca kullanıcı deneyimini kesintiye uğratmadan güncellemeleri kolaylaştırdığını unutmayın.
Workbox'u incelemeye başlamadan önce, Workbox'un ne yaptığını anlayabilmek için hizmet çalışanı yaşam döngüsünü anlamanız önemlidir.
Terimleri tanımlama
Hizmet çalışanı yaşam döngüsüne geçmeden önce, bu yaşam döngüsünün işleyiş şekliyle ilgili bazı terimleri tanımlamak faydalı olacaktır.
Kontrol ve kapsam
Kontrol fikri, hizmet işçilerinin işleyişini anlamak için çok önemlidir. Bir hizmet çalışanı tarafından kontrol edildiği açıklanan sayfa, hizmet çalışanının kendi adına ağ isteklerini durdurmasına izin veren bir sayfadır. Hizmet çalışanı mevcut ve belirli bir kapsamda sayfa için iş yapabiliyor.
Kapsam
Hizmet işçisinin kapsamı, web sunucusundaki konumuna göre belirlenir.
Bir hizmet çalışanı /subdir/index.html
adresinde bulunan bir sayfada çalışıyorsa ve /subdir/sw.js
adresinde bulunuyorsa hizmet çalışanının kapsamı /subdir/
olur.
Kapsam kavramını uygulamada görmek için şu örneği inceleyin:
- https://service-worker-scope-viewer.glitch.me/subdir/index.html adresine gidin.
Sayfayı kontrol eden bir hizmet çalışanı olmadığını belirten bir mesaj gösterilir.
Ancak bu sayfa,
https://service-worker-scope-viewer.glitch.me/subdir/sw.js
kaynağından bir hizmet çalışanı kaydediyor. - Sayfayı tekrar yükleyin. Hizmet çalışanı kaydedilmiş ve etkinleştirilmiş olduğundan sayfayı kontrol ediyor. Hizmet çalışanının kapsamını, mevcut durumunu ve URL'sini içeren bir form görünür. Not: Sayfanın yeniden yüklenmesi, kapsamla değil, daha sonra açıklanacak olan hizmet çalışanı yaşam döngüsü ile ilgilidir.
- Ardından https://service-worker-scope-viewer.glitch.me/index.html adresine gidin. Bu kaynağa bir hizmet çalışanı kaydedilmiş olsa bile hâlâ mevcut bir hizmet çalışanı olmadığını belirten bir mesaj gösteriliyor. 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
adresinden yüklenen hizmet çalışanı yalnızca /subdir/
veya alt ağacında bulunan sayfaları kontrol edebilir.
Kapsamlandırma varsayılan olarak yukarıda açıklandığı şekilde çalışı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.
Hizmet çalışanı kapsamını bir kaynağın alt kümesiyle sınırlamak için çok iyi bir nedeniniz yoksa kapsamı olabildiğince geniş olacak şekilde web sunucusunun kök dizininden bir hizmet çalışanı yükleyin ve Service-Worker-Allowed
başlığıyla ilgili endişelenmeyin. Bu şekilde herkes için çok daha basit olur.
Müşteri
Bir hizmet çalışanının sayfayı kontrol ettiği söylendiğinde, aslında bir istemci kontrol edilmektedir.
İstemci, URL'si ilgili hizmet çalışanının kapsamına giren açık bir sayfadır.
Daha açık belirtmek gerekirse bunlar WindowClient
örnekleridir.
Yeni bir hizmet çalışanının yaşam döngüsü
Bir hizmet çalışanının bir sayfayı kontrol edebilmesi için önce sayfanın oluşturulması gerekir. Etkin bir hizmet işçisi olmayan bir web sitesi için yepyeni bir hizmet işçisi dağıtıldığında ne olduğuna bakalı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:
- Kullanıcının bir web sitesine yaptığı ilk ziyaret, kayıtlı bir hizmet çalışanı olmadan gerçekleştiği için kayıt yapmadan önce sayfanın tamamen yüklenmesini bekleyin. Bu sayede, hizmet çalışanı herhangi bir öğeyi önceden önbelleğe alırsa bant genişliği çekişmesi önlenir.
- Hizmet çalışanı iyi desteklenmesine rağmen hızlı bir kontrol, desteklenmediği tarayıcılarda hataları önlemeye yardımcı olur.
- Sayfa tamamen yüklendiğinde ve hizmet çalışanı destekleniyorsa
/sw.js
öğesini kaydedin.
Anlamanız gereken bazı önemli noktalar şunlardır:
- Hizmet çalışanları yalnızca HTTPS veya localhost üzerinden kullanılabilir.
- Bir hizmet çalışanının içeriği söz dizimi hataları içeriyorsa kayıt başarısız olur ve hizmet çalışanı atılır.
- Hatırlatma: Hizmet çalışanları bir kapsamda çalışır. Burada kapsam, kök dizinden yüklendiği için kaynağın tamamıdır.
- Kayıt işlemi başladığında hizmet çalışanı durumu
'installing'
olarak ayarlanır.
Kayıt tamamlandıktan sonra yükleme başlar.
Kurulum
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 tetiklenmez.
install
etkinliği için geri çağırma işlevi, addEventListener
ile işleyicinin kapsamına 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 önceden önbelleğe alır.
Ön önbelleğe alma hakkında daha sonra bolca konuşma fırsatımız olacak. Şimdilik event.waitUntil
işlevine odaklanalım. event.waitUntil
bir vaat kabul eder ve bu vaat çözülene kadar bekler.
Bu örnekte, söz konusu promise iki eşzamansız işlem yapar:
'MyFancyCache_v1'
adlı yeni birCache
örneği oluşturur.- Önbelleğe alma işlemi tamamlandıktan sonra, bir dizi öğe URL'si, asenkron
addAll
yöntemi kullanılarak önceden önbelleğe alınır.
event.waitUntil
'e iletilen sözler reddedilirse yükleme başarısız olur.
Bu durumda hizmet çalışanı atılır.
Sözler çözüme kavuşursa yükleme başarılı olur ve hizmet çalışanının durumu 'installed'
olarak değişir, ardından etkinleştirilir.
Etkinleştirme
Kayıt ve yükleme başarılı olursa hizmet çalışanı etkinleştirilir ve durumu 'activating'
olur. Hizmet çalışanının activate
etkinliğinde etkinleştirme sırasında işlem yapılabilir.
Bu etkinlikte tipik bir görev eski önbellekleri kaldırmaktır ancak yepyeni bir hizmet çalışanı için bu şu anda alakalı değildir ve hizmet çalışanı güncellemelerinden bahsettiğimizde daha ayrıntılı olarak ele alınacaktır.
Yeni hizmet çalışanları için activate
, install
başarılı olduktan hemen sonra tetiklenir.
Etkinleştirme işlemi tamamlandıktan sonra servis çalışanının durumu 'activated'
olur.
Varsayılan olarak yeni hizmet çalışanının, bir sonraki gezinme veya sayfa yenileme işlemine kadar sayfayı kontrol etmeye başlamadığını unutmayın.
Hizmet çalışanı güncellemelerini işleme
İlk hizmet çalışanı dağıtıldıktan sonra muhtemelen 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, aşağıdaki durumlarda bir hizmet çalışanının güncellemelerini kontrol eder:
- Kullanıcı, hizmet çalışanının kapsamındaki bir sayfaya gider.
navigator.serviceWorker.register()
, şu anda yüklü olan hizmet işçisinden farklı bir URL ile çağrılır. Ancak hizmet işçisinin URL'sini değiştirmeyin.navigator.serviceWorker.register()
, yüklü hizmet çalışanıyla aynı URL ile ancak farklı bir kapsamda çağrılır. Mümkünse kapsamı bir kaynağın kökünde tutarak bu durumdan kaçının.- Son 24 saat içinde
'push'
veya'sync'
gibi etkinlikler tetiklendiğinde. Ancak bu etkinliklerden henüz endişelenmeyin.
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" güncellediğini de bilmeniz gerekir. Bir hizmet çalışanının URL'sinin veya kapsamının değişmediği varsayıldığında, şu anda yüklü olan bir hizmet çalışanı yalnızca içeriği değişirse yeni bir sürüme güncellenir.
Tarayıcılar değişiklikleri birkaç şekilde algılar:
- Varsa
importScripts
tarafından istenen komut dosyalarında bayt bayt değişiklikler - 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.
Buradaki ağır işler tarayıcı tarafından yapılır. Tarayıcının, hizmet çalışanının içeriklerindeki değişiklikleri güvenilir bir şekilde algılamak için ihtiyaç duyduğu her şeye sahip olduğundan emin olmak amacıyla HTTP önbelleğini dosyayı tutmaya yönlendirmeyin ve dosya adını değiştirmeyin. Tarayıcı, bir hizmet çalışanının kapsamında yeni bir sayfaya gidildiğinde otomatik olarak güncelleme kontrolleri gerçekleştirir.
Güncelleme kontrollerini manuel olarak tetikleme
Güncellemeler söz konusu olduğunda kayıt mantığı genellikle değişmez. Bununla birlikte, bir web sitesindeki oturumların uzun süreli olması istisna olarak kabul edilebilir. Bu durum, uygulamanın yaşam döngüsünün başında genellikle bir gezinme isteğiyle karşılaşması nedeniyle gezinme isteklerinin nadir olduğu tek sayfalık uygulamalarda görülebilir. Bu gibi durumlarda ana mesaj dizisinde manuel güncelleme tetiklenebilir:
navigator.serviceWorker.ready.then((registration) => {
registration.update();
});
Geleneksel web siteleri veya kullanıcı oturumlarının uzun süreli olmadığı durumlarda manuel güncellemeleri tetiklemeniz gerekmeyebilir.
Kurulum
Statik öğeler oluşturmak için bir paketleyici kullanıldığında bu öğelerin adında framework.3defa9d2.js
gibi karma oluşturma işlemleri bulunur.
Bu öğelerden bazılarının daha sonra çevrimdışı erişim için önceden önbelleğe alındığını varsayalım.
Bu durumda, güncellenen öğelerin önbelleğe alınması için bir hizmet çalışanı güncellemesi 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'
]);
}));
});
Bu örnek, daha önceki install
etkinliği örneğinden iki açıdan farklıdır:
'MyFancyCacheName_v2'
anahtarına sahip yeni birCache
örneği oluşturulur.- Önceden önbelleğe alınan öğe adları değişti.
Güncellenen hizmet çalışanının öncekinin yanında yüklendiğini unutmayın. Bu, açık sayfaların kontrolü hâlâ eski hizmet çalışanında olduğu ve yükleme işleminden sonra yeni hizmet çalışanının etkinleştirilene kadar bekleme durumuna girdiği anlamına gelir.
Varsayılan olarak, eski hizmet çalışanı tarafından kontrol edilen istemci olmadığında yeni bir hizmet çalışanı etkinleştirilir. Bu durum, ilgili web sitesine ait tüm açık sekmeler kapatıldığında gerçekleşir.
Etkinleştirme
Güncellenen bir hizmet çalışanı yüklendiğinde ve bekleme aşaması sona erdiğinde, bu hizmet çalışanı etkinleştirilir ve eski hizmet çalışanı atılır.
Güncellenen bir hizmet çalışanının activate
etkinliğinde sıklıkla yapılan bir işlem, eski önbellekleri kaldırmaktır.
caches.keys
ile tüm açık Cache
örneklerine ait anahtarları alarak ve tanımlanmış bir izin verilenler listesinde bulunmayan önbellekleri caches.delete
ile 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 kendiliğinden temizlenmez.
Bunu kendimiz yapmamız gerekiyor. Aksi takdirde depolama alanı kotalarını aşma riskimiz var.
İlk hizmet çalışanındaki 'MyFancyCacheName_v1'
güncel olmadığından, önbelleğe izin verilenler listesi 'MyFancyCacheName_v2'
'ü belirtecek şekilde güncellenir. Bu işlem, farklı ada sahip önbellekleri siler.
Eski önbellek kaldırıldıktan sonra activate
etkinliği sona erer.
Bu noktada yeni hizmet çalışanı sayfanın kontrolünü devralır ve eski hizmet çalışanını tamamen değiştirir.
Yaşam döngüsü devam eder
Hizmet çalışanı dağıtımını ve güncellemelerini yönetmek için Workbox'un mı yoksa doğrudan Hizmet Çalışanı API'sinin mi kullanıldığına bakılmaksızın, hizmet çalışanı yaşam döngüsünü anlamak faydalıdır. Bu bilgilerle, hizmet çalışanı davranışları gizemli olmaktan çıkıp daha mantıklı görünecektir.
Bu konuyu daha ayrıntılı incelemek isteyenler Jake Archibald'ın bu makalesine göz atabilir. Hizmet yaşam döngüsü ile ilgili birçok ayrıntı vardır ancak bu ayrıntılar öğrenilebilir ve Workbox'u kullanırken bu bilgilerden yararlanabilirsiniz.