Bazı web sitelerinin, sonuç hakkında bilgilendirilmeden hizmet işçisiyle iletişim kurması gerekebilir. Aşağıda bazı örnekler verilmiştir:
- Bir sayfa, hizmet çalışanına önceden önbelleğe alınacak URL'lerin listesini gönderir. Böylece kullanıcı bir bağlantıyı tıkladığında doküman veya sayfa alt kaynakları önbellekte hazır olur ve sonraki gezinme çok daha hızlı olur.
- Sayfa, hizmet çalışanından en çok okunan makaleleri alıp önbelleğe almasını ve böylece çevrimdışı olarak kullanılabilmesini ister.
Kritik olmayan bu tür görevleri hizmet işleyiciye devretmek, ana iş parçacığının kullanıcı etkileşimlerine yanıt verme gibi daha acil görevleri daha iyi işleyebilmesi için boşaltılmasını sağlar.
Bu rehberde, standart tarayıcı API'lerini ve Workbox kitaplığını kullanarak sayfadan hizmet işleyiciye tek yönlü bir iletişim tekniğinin nasıl uygulanacağını inceleyeceğiz. Bu tür kullanım alanlarını zorunlu önbelleğe alma olarak adlandıracağız.
Üretim destek kaydı
1-800-Flowers.com, kategori sayfalarındaki en popüler öğeleri önceden almak ve ardından ürün ayrıntıları sayfalarına gitmeyi hızlandırmak için postMessage()
aracılığıyla hizmet işçileriyle zorunlu önbelleğe alma (ön yükleme) özelliğini uyguladı.
Hangi öğelerin önceden belleneceğine karar vermek için karma bir yaklaşım kullanırlar:
- Sayfa yüklenirken servis sağlayıcı çalışanından en iyi 9 öğeyle ilgili JSON verilerini almasını ve elde edilen yanıt nesnelerini önbelleğe eklemesini ister.
- Kalan öğeler için
mouseover
etkinliğini dinlerler. Böylece, kullanıcı imleci bir öğenin üzerine getirdiğinde "talep" üzerine kaynak getirme işlemini tetikleyebilirler.
JSON yanıtlarını depolamak için Cache API'yi kullanırlar:
Kullanıcı bir öğeyi tıkladığında, ağ bağlantısına gerek kalmadan öğeyle ilişkili JSON verileri önbellekten alınabilir. Bu da gezinmeyi hızlandırır.
Workbox'u kullanma
Workbox, pencere bağlamında çalışacak bir modül grubu olan workbox-window
paketi aracılığıyla bir hizmet çalışanına mesaj göndermenin kolay bir yolunu sağlar. Bu hizmetler, Service Worker'da çalışan diğer Workbox paketlerinin tamamlayıcısıdır.
Sayfayı hizmet çalışanıyla iletişim kurmak için önce kayıtlı hizmet çalışanına bir Workbox nesne referansı alın:
const wb = new Workbox('/sw.js');
wb.register();
Böylece kayıt alma, etkinleştirmeyi kontrol etme veya temel iletişim API'sini düşünme zahmetine girmeden mesajı doğrudan beyan edilmiş olarak gönderebilirsiniz:
wb.messageSW({"type": "PREFETCH", "payload": {"urls": ["/data1.json", "data2.json"]}}); });
Hizmet çalışanı, bu mesajları dinlemek için bir message
işleyici uygular. İsteğe bağlı olarak bir yanıt döndürebilir ancak bu gibi durumlarda gerekli değildir:
self.addEventListener('message', (event) => {
if (event.data && event.data.type === 'PREFETCH') {
// do something
}
});
Tarayıcı API'lerini kullanma
Workbox kitaplığı ihtiyaçlarınız için yeterli değilse tarayıcı API'lerini kullanarak pencere-hizmet çalışanı iletişimini nasıl uygulayabileceğiniz aşağıda açıklanmıştır.
postMessage API, sayfadan hizmet işleyiciye tek yönlü bir iletişim mekanizması oluşturmak için kullanılabilir.
Sayfa, hizmet çalışanı arayüzünde postMessage()
çağrısı yapıyor:
navigator.serviceWorker.controller.postMessage({
type: 'MSG_ID',
payload: 'some data to perform the task',
});
Hizmet çalışanı, bu mesajları dinlemek için bir message
işleyici uygular.
self.addEventListener('message', (event) => {
if (event.data && event.data.type === MSG_ID) {
// do something
}
});
{type : 'MSG_ID'}
özelliği kesinlikle gerekli değildir ancak sayfanın hizmet çalışanına farklı türde talimatlar göndermesine (yani "önceden getirmek" ve "depolama alanını temizlemek için") izin vermenin bir yoludur. Hizmet çalışanı, bu işarete bağlı olarak farklı yürütme yollarına ayrılabilir.
İşlem başarılı olursa kullanıcı bu durumdan yararlanabilir. İşlem başarısız olursa ana kullanıcı akışında değişiklik olmaz. Örneğin, 1-800-Flowers.com ön önbelleğe almaya çalıştığında sayfanın, hizmet çalışanının başarılı olup olmadığını bilmesi gerekmez. Bu durumda kullanıcı daha hızlı bir gezinme deneyimi yaşar. Yoksa sayfanın yeni sayfaya gitmesi gerekir. Sadece biraz daha uzun sürecek.
Basit bir ön getirme örneği
Zorunlu önbelleğe alma'nın en yaygın uygulamalarından biri ön beslemedir. Bu, kullanıcı ilgili URL'ye geçmeden önce, gezinmeyi hızlandırmak için söz konusu URL'nin kaynaklarını getirme anlamına gelir.
Sitelerde ön getirmeyi uygulamanın farklı yolları vardır:
- Sayfalarda bağlantı ön getirme etiketleri kullanma: Kaynaklar beş dakika boyunca tarayıcı önbelleğinde tutulur. Ardından, kaynak için normal
Cache-Control
kuralları geçerli olur. - Önceden getirme kaynağının ömrünü bu sınırın ötesine çıkarmak için önceki tekniği hizmet işleyicisinde bir çalışma zamanında önbelleğe alma stratejisiyle tamamlama.
Belgeleri veya belirli öğeleri (JS, CSS vb.) önceden getirme gibi nispeten basit önceden getirme senaryoları için bu teknikler en iyi yaklaşımdır.
Ek mantık gerekiyorsa (ör. dahili URL'lerini almak için ön getirme kaynağını (JSON dosyası veya sayfa) ayrıştırma) bu görevi tamamen hizmet işleyiciye devretmek daha uygundur.
Bu tür işlemleri hizmet işleyiciye devretmenin avantajları şunlardır:
- Getirme ve getirme sonrası işleme (daha sonra kullanıma sunulacaktır) işlemlerinin ağır yükünü ikincil bir iş parçacığına aktarma. Bunu yaparak ana iş parçacığının, kullanıcı etkileşimlerine yanıt verme gibi daha önemli görevleri yerine getirmesini sağlar.
- Birden fazla istemcinin (ör. sekmeler) ortak bir işlevi yeniden kullanmasına izin verme ve hatta ana iş parçacığı engellenmeden hizmeti aynı anda çağırma.
Ürün ayrıntıları sayfalarını önceden getir
Öncelikle hizmet çalışanı arayüzünde postMessage()
kullanın ve önbelleğe alınacak bir URL dizisi iletin:
navigator.serviceWorker.controller.postMessage({
type: 'PREFETCH',
payload: {
urls: [
'www.exmaple.com/apis/data_1.json',
'www.exmaple.com/apis/data_2.json',
],
},
});
Hizmet çalışanında, etkin bir sekme tarafından gönderilen iletileri yakalayıp işlemek için bir message
işleyici uygulayın:
addEventListener('message', (event) => {
let data = event.data;
if (data && data.type === 'PREFETCH') {
let urls = data.payload.urls;
for (let i in urls) {
fetchAsync(urls[i]);
}
}
});
Önceki kodda, URL dizisini iterlemek ve her biri için bir getirme isteği göndermek üzere fetchAsync()
adlı küçük bir yardımcı işlev tanıtmıştık:
async function fetchAsync(url) {
// await response of fetch call
let prefetched = await fetch(url);
// (optionally) cache resources in the service worker storage
}
Yanıt alındığında kaynağın önbelleğe alma üst bilgilerini kullanabilirsiniz. Ancak çoğu durumda (ör. ürün ayrıntıları sayfalarında) kaynaklar önbelleğe alınmaz (yani Cache-control
no-cache
başlığı vardır). Bu gibi durumlarda, getirilen kaynağı hizmet çalışanı önbelleğine kaydederek bu davranışı geçersiz kılabilirsiniz. Bu, dosyanın çevrimdışı senaryolarda yayınlanmasına olanak tanıması açısından da avantajlıdır.
JSON verilerinin ötesinde
JSON verileri bir sunucu uç noktasından getirildikten sonra genellikle önceden getirmeye değer başka URL'ler de içerir (ör. bu birinci düzey verilerle ilişkili bir resim veya diğer uç nokta verileri).
Örneğimizde, döndürülen JSON verilerinin bir market alışverişi sitesinin bilgileri olduğunu varsayalım:
{
"productName": "banana",
"productPic": "https://cdn.example.com/product_images/banana.jpeg",
"unitPrice": "1.99"
}
Ürün listesini yinelemek için fetchAsync()
kodunu değiştirin ve her biri için hero resmi önbelleğe alın:
async function fetchAsync(url, postProcess) {
// await response of fetch call
let prefetched = await fetch(url);
//(optionally) cache resource in the service worker cache
// carry out the post fetch process if supplied
if (postProcess) {
await postProcess(prefetched);
}
}
async function postProcess(prefetched) {
let productJson = await prefetched.json();
if (productJson && productJson.product_pic) {
fetchAsync(productJson.product_pic);
}
}
404 hataları gibi durumlar için bu kodun etrafına bazı istisna işleme ekleyebilirsiniz. Ancak ön besleme için bir hizmet çalışanı kullanmanın avantajı, sayfa ve ana iş parçacığı için çok fazla soruna yol açmadan başarısız olabilmesidir. Ayrıca, önceden getirilen içeriğin son işleme süreciyle ilgili daha ayrıntılı bir mantık kullanabilir, böylece içeriği daha esnek ve işlediği verilerle birbirinden ayırabilirsiniz. Kendinize sınır koyabilirsiniz.
Sonuç
Bu makalede, sayfa ile hizmet çalışanı arasında tek yönlü iletişimin yaygın bir kullanım alanını ele aldık: zorunlu önbelleğe alma. Ele alınan örnekler yalnızca bu kalıbın bir kullanım şeklini göstermeyi amaçlamaktadır. Aynı yaklaşım, çevrimdışı tüketim için en popüler makaleleri isteğe bağlı olarak önbelleğe alma, yer işareti ekleme ve diğer kullanım alanları gibi diğer kullanım alanlarına da uygulanabilir.
Sayfa ve hizmet çalışanı iletişimi için daha fazla kalıp görmek isterseniz şu makalelere göz atın:
- Güncellemeleri yayınlama: Önemli güncellemeler (ör. web uygulamasının yeni bir sürümü kullanıma sunuldu) hakkında bilgi vermek için sayfayı hizmet çalışanından çağırma.
- İki yönlü iletişim: Bir görevi bir hizmet çalışanına delege etme (ör. ağır bir indirme) ve sayfayı ilerleme durumu hakkında bilgilendirme.