Service Worker'ları düşünürken ne düşünmelisiniz?
Service Worker'lar güçlüdür ve kesinlikle öğrenmeye değerdir. Kullanıcılarınıza yepyeni bir deneyim seviyesi sunmanızı sağlar. Siteniz anında yüklenebilir. Çevrimdışı olarak çalışabilir. Platforma özel bir uygulama olarak yüklenebilir ve her yönüyle gösterişli ama web'in erişimi ve özgürlüğüyle.
Ancak Service Worker'lar, çoğu web geliştiricisinin alışkın olduğu hiçbir şeye benzemez. Yoğun bir öğrenme süreciyle karşı karşıyalar ve dikkat etmeniz gereken bazı sorunlar var.
Google Developers ile kısa bir süre önce bir projede, hizmet çalışanlarını anlamaya yönelik ücretsiz bir oyun olan Service Workies üzerinde ortak çalıştık. Bu sistemi geliştirirken ve hizmet çalışanlarının karmaşık ayrıntılarıyla çalışırken birkaç sorunla karşılaştım. Bu konuda en çok yardımcı olan, birkaç betimleyici metafor bulmak oldu. Bu gönderide, bu zihinsel modelleri keşfedecek ve hizmet çalışanlarını zorlayıcı ve müthiş bir deneyime dönüştüren paradoksal özelliklere odaklanacağız.
Aynı ancak farklı
Service Worker'ınızı kodlarken size tanıdık gelecek birçok şey vardır. En sevdiğiniz yeni JavaScript dili özelliklerini kullanabilirsiniz. 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 taahhütlerle yönetirsiniz.
Ancak diğer hizmet çalışanı davranışları kafanızın karışmasına neden olur. Özellikle sayfayı yenilediğinizde kod değişikliklerinizin uygulandığını görmüyorsanız.
Yeni katman
Normalde, bir site oluştururken düşünmeniz gereken yalnızca iki katman vardır: istemci ve sunucu. Service Worker, ortasında yer alan yepyeni bir katmandır.
Service Worker'ı, sitenizin kullanıcınızın tarayıcısına sitenizin yükleyebileceği bir tür tarayıcı uzantısı olarak düşünebilirsiniz. Uzantı yüklendikten sonra hizmet çalışanı, 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 de Service Worker'ı güncellemek için yeterli değildir. Her katmanın kendi güncelleme kuralları vardır.
Service Workies oyununda Service Worker'ın yaşam döngüsüyle ilgili birçok ayrıntıya değiniyor ve onunla birçok pratik yapma alıştırması yapın.
Güçlü ancak sınırlı
Sitenizde bir Service Worker'ın olması size inanılmaz avantajlar sağlar. Siteniz:
- kullanıcı çevrimdışı olsa bile kusursuz bir şekilde çalışmak
- Önbelleğe alma yoluyla büyük performans iyileştirmeleri elde etme
- push bildirimlerini kullanın
- PWA olarak yüklenmelidir.
Service Worker'ların yapabildiği kadar tasarım nedeniyle sınırlıdır. Sitenizle eşzamanlı olarak veya aynı iş parçacığında hiçbir şey yapamazlar. Bu durumda şunlara erişilemez:
- localStorage
- DOM
- pencere
Neyse ki sayfanızın hizmet çalışanıyla iletişim kurabileceği, doğrudan postMessage
, bire bir Mesaj Kanalları ve bire-bir çok Yayın Kanalları gibi birkaç yol vardır.
Uzun ömürlü ama 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ı bu hizmet çalışanını, kullanıcı sitenize tekrar döndüğünde hazır olması için saklar. İlk istek yapılmadan önce Service Worker'a müdahale etme ve sayfanın kontrolünü ele geçirme fırsatı sunulur. Bu, bir sitenin çevrimdışı çalışmasına olanak tanır. Service Worker, kullanıcının internet bağlantısı olmasa bile sayfanın önbelleğe alınmış bir sürümünü sunabilir.
Service Workies bölümünde, bu kavramı Kolohe'un (yardımcı bir hizmet çalışanı) müdahale ederek isteklere müdahale ettiği ve ele aldığı görselleştirdik.
Durduruldu
Service Worker'lar ö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 istemiyor. Durdurulmak, sonlandırılması ile aynı şey değildir. Service Worker 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ının bunu bilmesi için bir yönteme ihtiyacı vardır. İşte event.waitUntil()
bu noktada devreye giriyor. Bu yöntem, kullanıldığı yaşam döngüsünü uzatarak hem durmasını hem de biz hazır olana kadar yaşam döngüsünün bir sonraki aşamasına geçmesini önler. Bu, önbellekleri ayarlamamız, kaynakları ağdan getirmemiz ve benzer işlemler için bize zaman kazandırır.
Bu örnek, tarayıcıya, assets
önbelleği oluşturulup bir kılıç resmiyle doldurulana kadar hizmet çalışanımızın yükleme işlemini tamamlamadığını belirtir:
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 gerçekleştiğinde, hizmet çalışanının genel kapsamı sıfırlanır. Bu nedenle, hizmet çalışanınızda herhangi bir genel durum kullanmamaya dikkat edin. Aksi takdirde, tekrar uyandığında ve beklediğinden farklı bir duruma sahip olduğunda üzülürsünüz.
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 istekte bir numara kaydeder (ör. 0.13981866382421893
). hasHandledARequest
değişkeni de true
olarak değişir. Bu noktada Service Worker bir süre boşta kaldığından tarayıcı bunu durdurur. Bir sonraki istek olduğunda Service Worker'a tekrar ihtiyaç duyulur ve tarayıcı bunu uyandırır. Komut dosyası tekrar değerlendirilir. Şimdi hasHandledARequest
, false
olarak sıfırlandı ve favoriteNumber
adı tamamen farklı: 0.5907281835659033
.
Service Worker'da, depolandı 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.
Service Workies bölüm 3'te durdurulan hizmet çalışanımızı uyandırmayı beklerken tüm renklerini kaybetmiş olarak görselleştiriyoruz.
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 Service Worker'ı düzenlemiş olmazsınız. Service Worker'lar değiştirilemez. Bunun yerine yepyeni bir video hazırlıyorsunuz. Bu yeni hizmet çalışanı (buna SW2 diyelim) yüklenecek, ancak henüz etkinleşmeyecek. Mevcut hizmet çalışanının (SW1) sonlandırılmasını (kullanıcı sitenizden ayrıldığında) beklemek gerekir.
Başka bir hizmet çalışanının önbellekleriyle karışıklık
SW2, yükleme sırasında genellikle önbellek oluşturup doldurarak ayarların yapılmasını sağlayabilir. Ama dikkat edin: Bu yeni Service Worker, mevcut Service Worker'ı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şleri tamamen bozabilir. Sorun yaşamanıza neden olabilecek bazı örnekler:
- SW2, SW1'in etkin olarak kullandığı bir önbelleği silebilir.
- SW2, SW1'in kullandığı bir önbelleğin içeriğini düzenleyebilir ve bu da SW1'in sayfanın beklemediği öğelerle yanıt vermesine neden olabilir.
Atlamayı atlaBekleme
Ayrıca Service Worker, yükleme işlemi tamamlanır tamamlanmaz sayfanın kontrolünü ele geçirmek için riskli skipWaiting()
yöntemini de kullanabilir. Kasıtlı olarak hatalı bir hizmet çalışanını değiştirmeye çalışmadığınız sürece bu genellikle kötü bir fikirdir. Yeni Service Worker, geçerli sayfanın beklemediği şekilde 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, kullanılan önbellek adlarının sürümlerini 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 version
öğesini, önceki Service Worker'dan tamamen ayrı bir önbellekle ihtiyaç duyduğu işlemleri yapabilmesi için güçlendirirsiniz.
Temizliği sonlandır
Service Worker'ınız activated
durumuna ulaştığında hizmetin ele geçirildiğini anlarsınız ve önceki hizmet çalışanı yedeklenir. Bu noktada, eski Service Worker'dan sonra temizlik yapılması önemlidir. Bu, kullanıcılarınızın önbellek depolama alanı sınırlarına uymakla kalmaz, aynı zamanda istemeden yapılabilecek hataları da önler.
caches.match()
yöntemi, eşleşme bulunan herhangi bir önbellekten öğe almak için sıklıkla 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
sitesinden eski önbelleği geri döndürecek ve büyük olasılıkla sitenizi bozacaktır.
Önceki Service Worker'ların ihtiyaç duymadığı önbelleğin silinmesinden sonra bu temizlik işleminin tek yapılması gerekir:
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 bloke etmesini önlemek için biraz çalışma ve disiplin gerekir ama zahmete değer.
Hizmet çalışanı yaklaşımı
Service Worker'lar üzerine düşünürken doğru bir zihniyet benimsemek, kendi çalışanlarınızı güvenle oluşturmanıza yardımcı olur. Bunları kavradıktan sonra kullanıcılarınız için muhteşem deneyimler oluşturabileceksiniz.
Oyun oynayarak tüm bunları anlamak istiyorsanız şanslısınız! Service Workies oyununda hizmet çalışanının çevrimdışı canavarları nasıl öldürdüğünü öğreneceksiniz.