Hizmet çalışanlarını düşünürken nasıl düşünmelisiniz?
Hizmet çalışanları güçlüdür ve kesinlikle öğrenmeye değerdir. Bu reklamlar, kullanıcılarınıza tamamen yeni bir deneyim sunmanıza olanak tanır. Siteniz anında yüklenebilir. Çevrimdışı çalışabilir. Platforma özel bir uygulama olarak yüklenebilir ve her açıdan şık bir deneyim sunabilir ancak web'in erişimi ve özgürlüğüyle.
Ancak hizmet çalışanları, çoğu web geliştiricisinin alıştığı hiçbir şeye benzemez. Bu tür uygulamalarda öğrenme süreci oldukça uzundur ve dikkat etmeniz gereken bazı zorluklar vardır.
Google Developers ile yakın zamanda hizmet çalışanlarını anlamanızı sağlayacak ücretsiz bir oyun olan Service Workies projesi üzerinde birlikte çalıştık. Uygulamayı oluştururken ve hizmet işçilerinin karmaşık ayrıntılarıyla çalışırken birkaç sorunla karşılaştım. En çok yardımcı olan şey, birkaç açıklayıcı metafor bulmaktı. Bu yayında bu zihinsel modelleri keşfedecek ve hizmet işçilerini hem zor hem de harika kılan paradoksal özellikleri anlamaya çalışacağız.
Aynı ama farklı
Hizmet işleyicinizi kodlarken birçok şey tanıdık gelecektir. En sevdiğiniz yeni JavaScript dil özelliklerini kullanabilirsiniz. Yaşam döngüsü etkinliklerini, kullanıcı arayüzü etkinliklerinde olduğu gibi dinlersiniz. Kontrol akışını, alıştığınız gibi promises ile yönetirsiniz.
Ancak diğer hizmet çalışanı davranışları kafanızın karışmasına neden oluyor. Özellikle sayfayı yenilediğinizde kod değişikliklerinizin uygulanmadığını gördüğünüzde.
Yeni bir katman
Normalde bir site oluştururken dikkate almanız gereken iki katman vardır: istemci ve sunucu. Hizmet çalışanı, ortada bulunan yepyeni bir katmandır.
Hizmet çalışanınızı, sitenizin kullanıcınızın tarayıcısından yükleyebileceği bir tür tarayıcı uzantısı olarak düşünebilirsiniz. Servis çalışanı, yüklendikten sonra siteniz için tarayıcıya güçlü bir orta katman ekleyerek sitenizi geliştirir. Bu hizmet çalışanı katmanı, sitenizin yaptığı tüm istekleri durdurup işleyebilir.
Hizmet çalışanı katmanının, tarayıcı sekmesinden bağımsız kendi yaşam döngüsü vardır. Basit bir sayfa yenileme, bir hizmet çalışanını güncellemek için yeterli değildir. Tıpkı bir sunucudaki kodun sayfa yenilenmesiyle güncellenmesini beklemeyeceğiniz gibi. Her katmanın güncellemeyle ilgili kendine özgü kuralları vardır.
Service Workies oyununda, servis çalışanı yaşam döngüsünün birçok ayrıntısını ele alıyoruz ve bu konuda bolca alıştırma yapmanızı sağlıyoruz.
Güçlü ancak sınırlı
Sitenizde bir hizmet çalışanı bulundurmak size inanılmaz avantajlar sağlar. Siteniz:
- Kullanıcı çevrimdışıyken bile sorunsuz şekilde çalışır.
- Önbelleğe alma yoluyla büyük performans iyileştirmeleri elde edin
- Push bildirimleri kullanın
- PWA olarak yüklenmelidir.
Hizmet işçileri, tasarım gereği sınırlı bir işleve sahiptir. Sitenizle senkronize veya aynı mesaj dizisinde işlem yapamaz. Bu nedenle aşağıdakilere erişemezsiniz:
- localStorage
- DOM
- pencere
Neyse ki sayfanızın hizmet işçisiyle iletişim kurmasının birkaç yolu vardır. Doğrudan postMessage
, bire bir Mesaj Kanalları ve bire çok Yayın Kanalları bunlardan bazılarıdır.
Uzun ömürlü ancak kısa ömürlü
Etkin bir hizmet çalışanı, kullanıcı sitenizden ayrıldıktan veya sekmeyi kapattıktan sonra bile çalışmaya devam eder. Tarayıcı, kullanıcı sitenize tekrar geldiğinde hazır olması için bu hizmet çalışanını saklar. İlk istek gönderilmeden önce hizmet çalışanı, isteği durdurup sayfanın kontrolünü ele alma şansı elde eder. Bu sayede site çevrimdışı çalışabilir. Hizmet çalışanı, kullanıcının internet bağlantısı olmasa bile sayfanın önbelleğe alınmış bir sürümünü sunabilir.
Service Workies'de bu kavramı, istekleri yakalayıp işleyen Kolohe (sevimli bir hizmet çalışanı) ile 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 kaynak israf etmek istemez. Durdurulma, feshedilme ile aynı şey değildir. Hizmet çalışanı yüklü ve etkin durumda kalır. Sadece uyku moduna geçirilir. Bir sonraki sefere ihtiyaç duyulduğunda (ör. bir isteği işlemek için) tarayıcı bu işlemi tekrar başlatır.
waitUntil
Sürekli olarak uykuya geçirilme olasılığı nedeniyle, hizmet çalışanınızın önemli bir şey yaptığında ve uykuya dalmak istemediğinde tarayıcıya bunu bildirmenin bir yoluna ihtiyacı vardır. Bu noktada event.waitUntil()
devreye girer. Bu yöntem, kullanıldığı yaşam döngüsünü uzatarak hem durdurulmasını hem de hazır olana kadar yaşam döngüsünün bir sonraki aşamasına geçmesini engeller. Bu sayede önbellekleri ayarlayabilir, ağdan kaynak getirebilir vb. işlemleri yapabiliriz.
Bu örnekte tarayıcıya, assets
önbelleği oluşturulup bir kılıç resmiyle doldurulana kadar hizmet işleyicimizin yükleme işleminin tamamlanmadığı bildirilmektedir:
self.addEventListener("install", event => {
event.waitUntil(
caches.open("assets").then(cache => {
return cache.addAll(["/weapons/sword/blade.png"]);
})
);
});
Global duruma dikkat edin
Bu başlatma/durdurma işlemi gerçekleştiğinde hizmet çalışanının genel kapsamı sıfırlanır. Bu nedenle, servis çalışanınızda herhangi bir genel durum kullanmamaya dikkat edin. Aksi takdirde, bir sonraki kez tekrar etkinleştirildiğinde beklediğinizden farklı bir durumla karşılaşırsınız.
Global durum kullanan şu örneği inceleyin:
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 için bir sayı (ör. 0.13981866382421893
) günlüğe kaydeder. hasHandledARequest
değişkeni de true
olarak değişir. Şimdi hizmet çalışanı bir süre boşta durduğundan tarayıcı onu durdurur. Bir sonraki istek geldiğinde hizmet çalışanına tekrar ihtiyaç duyulur ve tarayıcı onu uyandırır. Komut dosyası yeniden değerlendirilir. Artık hasHandledARequest
, false
olarak sıfırlandı ve favoriteNumber
tamamen farklı bir değere (0.5907281835659033
) sahip.
Bir hizmet çalışanında depolanan duruma güvenemezsiniz. Ayrıca, Mesaj Kanalları gibi öğelerin örneklerini oluşturmak da hatalara neden olabilir: Hizmet çalışanı her durduğunda/başladığında yepyeni bir örnek alırsınız.
Hizmet Çalışanları 3. Bölüm'de, durdurulan hizmet çalışanımızı uyandırılmayı beklerken tüm rengini kaybediyor olarak görselleştiriyoruz.
Birlikte ancak ayrı
Sayfanız aynı anda yalnızca bir hizmet çalışanı tarafından kontrol edilebilir. Ancak aynı anda iki hizmet çalışanı yüklenebilir. Hizmet çalışanı kodunuzda değişiklik yaptığınızda ve sayfayı yenilediğinizde aslında hizmet çalışanınızı hiç düzenlemezsiniz. Hizmet çalışanları sabit olur. Bunun yerine yeni bir tane oluşturuyorsunuz. Bu yeni hizmet çalışanı (SW2 olarak adlandıralım) yüklenir ancak henüz etkinleştirilmez. Mevcut hizmet çalışanının (SW1) sona ermesini (kullanıcınız sitenizden ayrıldığında) wait gerekir.
Başka bir hizmet çalışanının önbelleğini bozma
SW2, yükleme sırasında genellikle önbellekleri oluşturup doldurarak bazı ayarları yapabilir. Ancak bu yeni hizmet çalışanının, mevcut hizmet çalışanının erişebildiği her şeye erişimi olduğunu unutmayın. Dikkatli olmazsanız yeni bekleyen hizmet çalışanınız, mevcut hizmet çalışanınız için işleri gerçekten alt üst edebilir. Size sorun çıkarabilecek bazı örnekler:
- SW2, SW1'in etkin olarak kullandığı bir önbelleği silebilir.
- SW2, SW1'in kullandığı bir önbelleğin içeriğini düzenleyebilir. Bu da SW1'in sayfanın beklemediği öğelerle yanıt vermesine neden olur.
skipWaiting işlevini atlama
Hizmet çalışanları, yükleme işlemi tamamlanır tamamlanmaz sayfanın kontrolünü ele almak için riskli skipWaiting()
yöntemini de kullanabilir. Bu, hatalı bir hizmet çalışanını kasıtlı olarak değiştirmeye çalışmadığınız sürece genellikle kötü bir fikirdir. Yeni hizmet çalışanı, mevcut sayfanın beklemediği güncellenmiş kaynakları kullanıyor olabilir. Bu da hatalara ve böceklere neden olur.
Temiz bir başlangıç yapın
Hizmet çalışanlarınızın birbirini engellemesini önlemek için farklı önbellekler kullanmasını sağlayın. Bunu yapmanın en kolay yolu, kullandıkları önbellek adlarını sürümlere ayırmaktı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ğıttığınızda, version
değerini önceki hizmet çalışanından tamamen ayrı bir önbelleğe sahip olacak şekilde değiştirirsiniz.
Son temizlik
Servis çalışanınız activated
durumuna ulaştığında, görevi devraldığı ve önceki servis çalışanının artık gerekmediği anlaşılır. Bu noktada eski hizmet çalışanının ardından temizlik yapmak önemlidir. Bu yaklaşım, kullanıcılarınızın önbellek depolama alanı sınırlarını gözetmekle kalmaz, aynı zamanda istenmeyen hataları da önleyebilir.
caches.match()
yöntemi, eşleşmenin bulunduğu herhangi bir önbellekten öğe almak için sık kullanılan bir kısayoldur. Ancak önbellekleri, oluşturuldukları sırayla iterasyon yapar. app.js
komut dosyası dosyasının iki farklı önbellekte (assets-1
ve assets-2
) iki sürümü olduğunu 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
'ten eskisini döndürür ve büyük olasılıkla sitenizi bozar.
Önceki hizmet işçilerinin ardından temizlik yapmak için tek yapmanız gereken, yeni hizmet işçisinin ihtiyaç duymadığı tüm önbellekleri 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 birbirlerini yıpratmasını önlemek biraz çalışma ve disiplin gerektirir ancak buna değer.
Hizmet çalışanı bakış açısı
Hizmet çalışanlarını düşünürken doğru zihniyete sahip olmak, kendi çalışanlarınızı güvenle oluşturmanıza yardımcı olur. Bu özellikleri kullanmayı öğrendikten sonra kullanıcılarınız için inanılmaz deneyimler oluşturabilirsiniz.
Tüm bunları oyun oynayarak öğrenmek istiyorsanız şanslısınız. Çevrimdışı canavarları öldürmek için servis çalışanının yollarını öğreneceğiniz Service Workies oyununu oynayın.