Service Worker'ları düşünürken nasıl düşünmelisiniz?
Service Worker'lar güçlüdür ve kesinlikle öğrenmeye değerdir. Kullanıcılarınıza tamamen yeni bir deneyim düzeyi sunmanızı sağlarlar. Siteniz anında yüklenebilir. Çevrimdışı çalışabilir. Platforma özel bir uygulama olarak yüklenebilir ve her şeye sahipmiş gibi hisseder, ancak web'in sunduğu erişim ve özgürlükten yararlanır.
Ancak Service Worker'lar, çoğu web geliştiricimizin alışkın olduğu hiçbir şeye benzemez. Zor bir öğrenme eğrisi ve dikkat etmeniz gereken bazı engeller var.
Google Developers ile birlikte kısa bir süre önce, hizmet çalışanlarını anlamaya yönelik ücretsiz bir oyun olan Service Workies adlı proje üzerinde çalıştık. Bu projeyi geliştirirken ve hizmet çalışanlarının karmaşık ayrıntılarıyla çalışırken bazı sorunlarla karşılaştım. En çok yardımcı olan, birkaç betimleyici metafor bulmak oldu. Bu gönderide, bu zihinsel modelleri keşfedecek ve hizmet çalışanlarını zorba ve mükemmel yapan paradoksal özelliklere odaklanacağız.
Aynı ama farklı
Service Worker'ınızı kodlarken birçok şeye aşina olacaksınız. En sevdiğiniz yeni JavaScript dili özelliklerini kullanabilirsiniz. Tıpkı kullanıcı arayüzü etkinliklerinde olduğu gibi yaşam döngüsü olaylarını dinlersiniz. Kontrol akışını, alışkın olduğunuz gibi gelecek vadedere yönetiyorsunuz.
Ancak diğer hizmet çalışanı davranışları kafanızın karışmasına neden olur. Özellikle sayfayı yenilediğinizde ve kod değişikliklerinizin uygulanmadığını görürseniz.
Yeni katman
Normalde bir site oluştururken düşünmeniz gereken yalnızca iki katman vardır: istemci ve sunucu. Hizmet çalışanı, ortasında yer alan yepyeni bir katmandır.
Hizmet çalışanınızı, sitenizin kullanıcının tarayıcısına yükleyebileceği bir tarayıcı uzantısı gibi düşünün. Uzantı yüklendikten sonra Service Worker, tarayıcıyı güçlü bir orta katmanla siteniz için extends. Bu hizmet çalışanı katmanı, sitenizin gönderdiği tüm isteklere müdahale edip bunları işleyebilir.
Service Worker katmanının, tarayıcı sekmesinden bağımsız olarak kendi yaşam döngüsü vardır. Sunucuda dağıtılan kodun güncellenmesi için sayfa yenilemesinin beklemediğiniz gibi, basit bir sayfa yenilemesi bir Service Worker'ı güncellemek için yeterli değildir. Her katmanın güncelleme için kendi benzersiz kuralları vardır.
Service Workies oyununda hizmet çalışanının yaşam döngüsünün birçok ayrıntısına değiniyor ve onunla çalışma alıştırmaları yapıyoruz.
Güçlü ancak sınırlı
Sitenizde bir Service Worker'ın olması size inanılmaz avantajlar sağlar. Siteniz:
- Kullanıcı çevrimdışı olduğunda bile kusursuz bir şekilde çalışıyor
- önbelleğe alma yoluyla büyük performans iyileştirmeleri elde edebilir.
- push bildirimlerini kullanma
- PWA olarak yüklenmelidir.
Service Worker'ların yapabildiği kadar tasarımla sınırlıdır. Sitenizle eşzamanlı veya aynı ileti dizisinde hiçbir şey yapamazlar. Bu da aşağıdakilere erişemeyeceğiniz anlamına gelir:
- localStorage
- DOM
- pencere
Neyse ki sayfanızın doğrudan postMessage
, bire bir Mesaj Kanalları ve bire-çok Yayın Kanalları dahil olmak üzere hizmet çalışanıyla iletişim kurabileceği birkaç yol vardır.
Uzun ömürlü ama kısa ömürlü
Etkin bir hizmet çalışanı, bir kullanıcı sitenizden ayrıldıktan veya sekmeyi kapattıktan sonra bile hayatını sürdürür. Tarayıcı, kullanıcı sitenize geri döndüğünde bu hizmet çalışanının hazır olmasını sağlar. İlk istek yapılmadan önce, hizmet çalışanının isteği engellemesi ve sayfanın kontrolünü ele geçirme fırsatı olur. Bu, sitenin çevrimdışı çalışmasına olanak tanır. Kullanıcının internet bağlantısı olmasa bile Service Worker, sayfanın önbelleğe alınmış bir sürümünü sunabilir.
Hizmet İşleri'nde bu kavramı Kolohe'un (dost canlısı bir hizmet çalışanı) ele alarak isteklere müdahale edip bunları ele aldığı görselleştiriyoruz.
Durduruldu
Hizmet çalışanları ölümsüz gibi görünse de neredeyse her zaman durdurulabilir. Tarayıcı, şu anda hiçbir şey yapmayan bir hizmet çalışanı için kaynakları boşa harcamak istemez. Durmak, feshedilmesi ile aynı şey değildir. Hizmet çalışanı yüklü ve etkin durumda kalır. Sadece uyku moduna geçiriliyor. Bir sonraki gerektiğinde (ör. bir isteği işlemek için) tarayıcı bunu tekrar uyandırır.
waitUntil
Sürekli uykuya dalma olasılığı nedeniyle, hizmet çalışanınızın önemli bir şey yaptığını ve uyuyormuş gibi hissetmediğini tarayıcıya bildirmesinin bir yolu olmalıdır. İşte event.waitUntil()
bu noktada devreye giriyor. Bu yöntem, kullanıldığı yaşam döngüsünü uzatır. Böylece, biz hazır olana kadar aracın durmasını ve bir sonraki aşamaya geçmesini önler. Bu, önbellekleri ayarlamak, kaynakları ağdan getirmek vb. için bize zaman kazandırır.
Bu örnekte, assets
önbelleği oluşturulup bir kılıç resmi doldurulana kadar hizmet çalışanımızın yüklemeyi tamamlamadığı belirtilmektedir:
self.addEventListener("install", event => {
event.waitUntil(
caches.open("assets").then(cache => {
return cache.addAll(["/weapons/sword/blade.png"]);
})
);
});
Küresel duruma dikkat edin
Bu başlatma/durdurma gerçekleştiğinde, hizmet çalışanının genel kapsamı sıfırlanır. Bu nedenle, hizmet çalışanınızda genel durum kullanmamaya dikkat edin. Aksi takdirde, tekrar uyandığında ve beklediğinden farklı bir duruma sahip olduğunda üzgün olursunuz.
Genel durum kullanılan şu örneği düşünün:
const favoriteNumber = Math.random();
let hasHandledARequest = false;
self.addEventListener("fetch", event => {
console.log(favoriteNumber);
console.log(hasHandledARequest);
hasHandledARequest = true;
});
Bu hizmet çalışanı, her istek üzerine bir numara kaydeder. Örneğin, 0.13981866382421893
. hasHandledARequest
değişkeni de true
olarak değişir. Şimdi Service Worker bir süre boşta kaldığından tarayıcı bunu durdurur. Bir sonraki istek olduğunda hizmet çalışanı tekrar gerekli olur. Böylece tarayıcı isteği uyandırır. Komut dosyası tekrar değerlendirilir. Şimdi hasHandledARequest
, false
olarak sıfırlandı ve favoriteNumber
artık tamamen farklı: 0.5907281835659033
.
Service Worker'da depolanan durumuna güvenemezsiniz. Ayrıca, Mesaj Kanalları gibi örneklerin oluşturulması hatalara neden olabilir: Service Worker her durduğunda/başlatıldığında yepyeni bir örnek alırsınız.
Hizmet Çalışmaları bölüm 3'te, durdurulan hizmet çalışanımızın uyandırılmayı beklerken tüm renklerini kaybettiğini göz önünde bulunduruyoruz.
Birlikte ama ayrı
Sayfanız aynı anda yalnızca bir hizmet çalışanı tarafından kontrol edilebilir. Ancak aynı anda iki Service Worker yüklenebilir. Service Worker kodunuzda bir değişiklik yapıp sayfayı yenilediğinizde aslında hizmet çalışanınızı düzenlemiş olmazsınız. Service Worker'lar değiştirilemez. Onun yerine yepyeni bir model oluşturuyorsunuz. Bu yeni hizmet çalışanı (SW2 olarak adlandıralım) yüklenir, ancak henüz etkinleşmez. Mevcut hizmet çalışanının (SW1) sonlandırılmasını (kullanıcı sitenizden ayrıldığında) beklemesi gerekir.
Başka bir hizmet çalışanının önbellekleriyle karmaşa
SW2, yükleme sırasında genellikle önbellek oluşturup doldurarak kurulum işlemini tamamlar. Ancak dikkat: Bu yeni Service Worker, mevcut hizmet çalışanının erişebildiği her şeye erişebilir. Dikkatli olmazsanız yeni bekleyen hizmet çalışanınız, mevcut hizmet çalışanınız için işler karışabilir. Sorun yaşamanıza neden olabilecek bazı örnekler:
- SW2, SW1'in aktif olarak kullandığı bir önbelleği silebilir.
- SW2, SW1'in kullandığı bir önbelleğin içeriğini düzenleyerek SW1'in sayfanın beklemediği öğelerle yanıt vermesine neden olabilir.
Atlamayı atlaBekleme
Ayrıca hizmet çalışanı, yükleme işlemi tamamlanır tamamlanmaz sayfanın kontrolünü ele almak için riskli skipWaiting()
yöntemini de kullanabilir. Hatalı bir hizmet çalışanını kasıtlı olarak değiştirmeye çalışmadığınız sürece bu genellikle kötü bir fikirdir. Yeni hizmet çalışanı, geçerli sayfanın beklemediği güncellenmiş kaynaklar kullanıyor olabilir. Bu da hatalara ve hatalara yol açabilir.
Temizlemeye başla
Hizmet çalışanlarınızın birbirlerini bloke etmesini önlemenin yolu, farklı önbellekler kullandıklarından emin olmaktır. Bunu yapmanın en kolay yolu, kullandıkları önbellek adlarının sürümünü oluşturmaktır.
const version = 1;
const assetCacheName = `assets-${version}`;
self.addEventListener("install", event => {
caches.open(assetCacheName).then(cache => {
// confidently do stuff with your very own cache
});
});
Yeni bir hizmet çalışanı dağıtırken, önceki hizmet çalışanından tamamen ayrı bir önbellekle ihtiyaç duyduğu işlemi yapması için version
öğesini dokundurursunuz.
Temizlemeyi sonlandır
Hizmet çalışanınız activated
durumuna ulaştığında, hizmet çalışanı devraldığını ve önceki hizmet çalışanının yedekli olduğunu anlarsınız. Bu noktada, eski hizmet çalışanının ardından temizlik yapılması önemlidir. Yalnızca kullanıcılarınızın önbellek depolama alanı sınırlarına uymakla kalmaz, aynı zamanda istenmeyen hataları da önler.
caches.match()
yöntemi, eşleşme bulunan herhangi bir önbellekten öğe almak için genellikle kullanılan bir kısayoldur. Ancak önbelleklerde oluşturuldukları sırayla yinelenir. assets-1
ve assets-2
olmak üzere iki farklı önbellekte app.js
komut dosyası sürümüne sahip olduğunuzu varsayalım. Sayfanız, assets-2
içinde depolanan daha yeni komut dosyasını bekliyor. Ancak, eski önbelleği silmediyseniz caches.match('app.js')
, assets-1
uygulamasından eski önbelleği döndürecek ve muhtemelen sitenizi bozacaktır.
Önceki hizmet çalışanlarından sonra temizlik yapmak için yapılması gereken tek şey, yeni hizmet çalışanının ihtiyaç duymadığı önbelleği silmektir:
const version = 2;
const assetCacheName = `assets-${version}`;
self.addEventListener("activate", event => {
event.waitUntil(
caches.keys().then(cacheNames => {
return Promise.all(
cacheNames.map(cacheName => {
if (cacheName !== assetCacheName){
return caches.delete(cacheName);
}
});
);
});
);
});
Hizmet çalışanlarınızın birbirine karışmasını önlemek için biraz çalışma ve disiplin gerekir ancak bu zahmete değecektir.
Hizmet çalışanı düşünce yapısı
Service Worker'lar konusunda düşünürken doğru zihniyeti benimsemek, şirketinizi güvenle oluşturmanıza yardımcı olur. Bunları kavradıktan sonra kullanıcılarınız için harika deneyimler oluşturabileceksiniz.
Bir oyun oynayarak tüm bunları anlamak istiyorsanız şanslısınız. Service Workies oynayın. Bu bölümde, hizmet çalışanının çevrimdışı canavarları öldürmek için kullandığı yolları öğreneceksiniz.