Aşamalı web uygulamalarının temel özelliklerinden biri güvenilir olmalarıdır. Bu uygulamalar, kötü ağ koşullarında bile kullanıcıların ilgisini canlı tutarak ve anında geri bildirim sağlayarak öğeleri hızlı bir şekilde yükleyebilir. Bu nasıl mümkün olabilir? Service worker fetch
etkinliği sayesinde.
Getirme etkinliği
fetch
etkinliği, hem aynı kaynak hem de kaynaklar arası istekler için hizmet çalışanının kapsamındaki PWA tarafından yapılan her ağ isteğini engellememize olanak tanır. Yüklü bir hizmet çalışanından getirme işlemi, gezinme ve öğe isteklerine ek olarak, bir sitenin ilk yüklenmesinden sonraki sayfa ziyaretlerinin ağ çağrıları olmadan oluşturulmasına olanak tanır.
fetch
işleyici, URL'ler ve HTTP üstbilgileri dahil olmak üzere bir uygulamadan gelen tüm istekleri alır ve uygulama geliştiricinin bunları nasıl işleyeceğine karar vermesine olanak tanır.
Hizmet çalışanız bir isteği ağa yönlendirebilir, daha önce önbelleğe alınmış bir yanıtla yanıt verebilir veya yeni bir yanıt oluşturabilir. Seçim size kalmış. Basit bir örnek:
self.addEventListener("fetch", event => {
console.log(`URL requested: ${event.request.url}`);
});
İsteğe yanıt verme
Hizmet çalışanıza bir istek geldiğinde iki şey yapabilirsiniz: İsteği yoksayarak ağa gitmesine izin verebilir veya isteğe yanıt verebilirsiniz. Kullanıcı çevrimdışıyken bile hizmet çalışanın içinden gelen isteklere yanıt vererek PWA'nıza neyin ve nasıl döndürüleceğini seçebilirsiniz.
Gelen bir isteğe yanıt vermek için event.respondWith()
etkinlik işleyicisi içinden fetch
işlevini şu şekilde çağırın:
// fetch event handler in your service worker file
self.addEventListener("fetch", event => {
const response = .... // a response or a Promise of response
event.respondWith(response);
});
respondWith()
işlevini senkron olarak çağırmalı ve Response nesnesi döndürmelisiniz. Ancak getirme etkinliği işleyicisi tamamlandıktan sonra (ör. eşzamansız bir çağrı içinde) respondWith()
işlevini çağıramazsınız. Tam yanıtı beklemeniz gerekiyorsa respondWith()
öğesine, yanıtla çözümlenen bir Promise iletebilirsiniz.
Yanıt oluşturma
Fetch API sayesinde JavaScript kodunuzda HTTP yanıtları oluşturabilir ve bu yanıtlar Cache Storage API kullanılarak önbelleğe alınabilir ve bir web sunucusundan geliyormuş gibi döndürülebilir.
Yanıt oluşturmak için yeni bir Response
nesnesi oluşturun ve gövdesini, durum ve başlık gibi seçeneklerini ayarlayın:
const simpleResponse = new Response("Body of the HTTP response");
const options = {
status: 200,
headers: {
'Content-type': 'text/html'
}
};
const htmlResponse = new Response("<b>HTML</b> content", options)
Önbellekten yanıt verme
Bir hizmet çalışanından HTTP yanıtları sunmayı öğrendiğinize göre artık öğeleri cihazda depolamak için Caching Storage arayüzünü kullanmanın zamanı geldi.
PWA'dan alınan isteğin önbellekte olup olmadığını kontrol etmek için önbellek depolama API'sini kullanabilirsiniz. İsteğin önbellekte olması durumunda respondWith()
ile yanıt verebilirsiniz.
Bunu yapmak için önce önbellekte arama yapmanız gerekir. Üst düzey caches
arayüzünde bulunan match()
işlevi, kaynağınızdaki tüm mağazalarda veya tek bir açık önbellek nesnesinde arama yapar.
match()
işlevi, HTTP isteğini veya URL'yi bağımsız değişken olarak alır ve ilgili anahtarla ilişkili yanıtla çözümlenen bir söz döndürür.
// Global search on all caches in the current origin
caches.match(urlOrRequest).then(response => {
console.log(response ? response : "It's not in the cache");
});
// Cache-specific search
caches.open("pwa-assets").then(cache => {
cache.match(urlOrRequest).then(response => {
console.log(response ? response : "It's not in the cache");
});
});
Önbelleğe alma stratejileri
Dosyaların yalnızca tarayıcı önbelleğinden sunulması her kullanım alanına uygun değildir. Örneğin, kullanıcı veya tarayıcı önbelleği boşaltabilir. Bu nedenle, PWA'nız için öğe sunma stratejilerinizi kendiniz tanımlamanız gerekir.
Tek bir önbelleğe alma stratejisiyle sınırlı değilsiniz. Farklı URL kalıpları için farklı tanımlar yapabilirsiniz. Örneğin, minimum kullanıcı arayüzü öğeleri için bir strateji, API çağrıları için başka bir strateji ve resim ile veri URL'leri için üçüncü bir strateji kullanabilirsiniz.
Bunu yapmak için ServiceWorkerGlobalScope.onfetch
bölümündeki event.request.url
konusunu okuyun ve normal ifadeler veya URL kalıbı aracılığıyla ayrıştırın. (Bu yazı yazıldığı sırada URL kalıbı tüm platformlarda desteklenmiyordu.)
En yaygın stratejiler şunlardır:
- Önce Önbellek
- Önce önbelleğe alınmış bir yanıtı arar, bulunamazsa ağa geri döner.
- Önce Ağ
- Önce ağdan yanıt ister ve yanıt döndürülmezse önbellekte yanıt olup olmadığını kontrol eder.
- Yeniden Doğrulama Sırasında Eski
- Önbellekten bir yanıt sunarken arka planda en son sürümü ister ve öğe bir sonraki sefer istendiğinde kullanılmak üzere önbelleğe kaydeder.
- Yalnızca Ağ
- Her zaman ağdan bir yanıtla karşılık verir veya hata verir. Önbelleğe hiçbir zaman başvurulmaz.
- Yalnızca Önbellek
- Her zaman önbellekten bir yanıtla yanıt verir veya hata verir. Ağa hiçbir zaman danışılmaz. Bu strateji kullanılarak yayınlanacak öğelerin, istenmeden önce önbelleğe eklenmesi gerekir.
Önce önbellek
Bu stratejiyi kullanan hizmet çalışanı, önbellekte eşleşen isteği arar ve önbelleğe alınmışsa karşılık gelen yanıtı döndürür. Aksi takdirde yanıtı ağdan alır (isteğe bağlı olarak, gelecekteki aramalar için önbelleği günceller). Önbellek yanıtı veya ağ yanıtı yoksa istek hatayla sonuçlanır. Ağa gitmeden öğe yayınlamak genellikle daha hızlı olduğundan bu strateji, yeniliğe kıyasla performansa öncelik verir.
self.addEventListener("fetch", event => {
event.respondWith(
caches.match(event.request)
.then(cachedResponse => {
// It can update the cache to serve updated content on the next request
return cachedResponse || fetch(event.request);
}
)
)
});
Ağ öncelikli
Bu strateji, Önce Önbellek stratejisinin tam tersidir. İsteğin ağdan karşılanıp karşılanamayacağını kontrol eder ve karşılanamıyorsa önbellekten almaya çalışır. Örneğin, önbellek önce. Ne ağ yanıtı ne de önbellek yanıtı varsa istek hata verir. Ağdan yanıt almak genellikle önbellekten yanıt almaktan daha yavaştır. Bu stratejide performans yerine güncellenmiş içeriğe öncelik verilir.
self.addEventListener("fetch", event => {
event.respondWith(
fetch(event.request)
.catch(error => {
return caches.match(event.request) ;
})
);
});
Yeniden doğrulama sırasında eski
Yeniden doğrulama sırasında eski stratejisi, önbelleğe alınmış bir yanıtı hemen döndürür, ardından ağda güncelleme olup olmadığını kontrol eder ve güncelleme bulunursa önbelleğe alınmış yanıtı değiştirir. Bu strateji, önbelleğe alınmış bir kaynak bulunsa bile bir sonraki istekte güncellenmiş sürümü kullanmak için önbellekteki içeriği ağdan alınan içerikle güncellemeye çalışacağından her zaman bir ağ isteği oluşturur. Bu nedenle bu strateji, öncelikle önbellek stratejisinin hızlı sunumundan yararlanmanıza ve önbelleği arka planda güncellemenize olanak tanır.
self.addEventListener('fetch', event => {
event.respondWith(
caches.match(event.request).then(cachedResponse => {
const networkFetch = fetch(event.request).then(response => {
// update the cache with a clone of the network response
const responseClone = response.clone()
caches.open(url.searchParams.get('name')).then(cache => {
cache.put(event.request, responseClone)
})
return response
}).catch(function (reason) {
console.error('ServiceWorker fetch failed: ', reason)
})
// prioritize cached response over network
return cachedResponse || networkFetch
}
)
)
})
Yalnızca ağ
Yalnızca ağ stratejisi, tarayıcıların bir hizmet çalışanı veya Cache Storage API olmadan nasıl davrandığına benzer. İstekler yalnızca ağdan getirilebilen kaynakları döndürür. Bu özellik genellikle yalnızca internet üzerinden yapılan API istekleri gibi kaynaklar için yararlıdır.
Yalnızca önbellek
Yalnızca önbellek stratejisi, isteklerin hiçbir zaman ağa gitmemesini sağlar. Gelen tüm istekler, önceden doldurulmuş bir önbellek öğesiyle yanıtlanır. Aşağıdaki kod, yalnızca önbelleğe yanıt vermek için önbellek depolama alanının match
yöntemiyle fetch
etkinlik işleyicisini kullanır:
self.addEventListener("fetch", event => {
event.respondWith(caches.match(event.request));
});
Özel stratejiler
Yukarıdakiler yaygın önbelleğe alma stratejileri olsa da hizmet çalışanınız ve isteklerin nasıl işleneceği konusunda sorumluluk size aittir. Bunlardan hiçbiri ihtiyaçlarınıza uygun değilse kendi şablonunuzu oluşturun.
Örneğin, güncellenmiş içeriğe öncelik vermek için zaman aşımıyla birlikte önce ağ stratejisi kullanabilirsiniz ancak yalnızca yanıt belirlediğiniz eşik içinde görünürse. Ayrıca, önbelleğe alınmış bir yanıtı ağ yanıtıyla birleştirip hizmet çalışanından karmaşık bir yanıt oluşturabilirsiniz.
Öğeleri güncelleme
PWA'nızın önbelleğe alınmış öğelerini güncel tutmak zor olabilir. Bu amaçla kullanılan yöntemlerden biri "yeniden doğrulama sırasında eski" stratejisidir ancak bu tek yöntem değildir. Güncelleme bölümünde, uygulamanızın içeriğini ve öğelerini güncel tutmak için farklı teknikler öğreneceksiniz.
Kaynaklar
- MDN'de Fetch etkinliği
- The Offline Cookbook (Çevrimdışı Yemek Kitabı)
- MDN'de önbellek eşleşmesi