Bazı senaryolarda, hizmet çalışanı belirli bir etkinlik hakkında bilgi vermek için kontrol ettiği etkin sekmelerden biriyle proaktif olarak iletişim kurması gerekebilir. Örnekler:
- Sayfaya, hizmet çalışanın yeni bir sürümü yüklendiğinde bilgi verilir. Böylece sayfa, kullanıcının yeni işlevselliğe hemen erişebilmesi için "Yenilemek için güncelle" düğmesini gösterebilir.
- Kullanıcıya, hizmet çalışanı tarafında gerçekleşen önbelleğe alınmış verilerdeki bir değişiklik hakkında bilgi vermek için "Uygulama artık çevrimdışı çalışmaya hazır" veya "İçeriğin yeni sürümü mevcut" gibi bir gösterge görüntülenir.
Hizmet çalışanının iletişimi başlatmak için sayfadan mesaj alması gerekmeyen bu tür kullanım alanlarına "yayın güncellemeleri" diyeceğiz. Bu kılavuzda, standart tarayıcı API'lerini ve Workbox kitaplığını kullanarak sayfalar ile hizmet çalışanları arasında bu tür bir iletişimi uygulamanın farklı yollarını inceleyeceğiz.
Üretim vakaları
Tinder
Tinder PWA, sayfadaki önemli hizmet çalışanı yaşam döngüsü anlarını ("yüklendi", "kontrol edildi" ve "etkinleştirildi") dinlemek için workbox-window kullanır. Bu sayede yeni bir hizmet çalışanı devreye girdiğinde "Güncelleme Mevcut" banner'ı gösterilir. Böylece kullanıcılar PWA'yı yenileyebilir ve en son özelliklere erişebilir:
Squoosh
Squoosh PWA'da, hizmet çalışanı çevrimdışı çalışmak için gerekli tüm öğeleri önbelleğe almasının ardından sayfaya bir mesaj gönderir. Bu mesajda, kullanıcıya özelliği bildirmek için "Çevrimdışı çalışmaya hazır" kısa iletisi gösterilir:
Workbox'ı kullanma
Hizmet çalışanının yaşam döngüsü etkinliklerini dinleme
workbox-window, önemli hizmet çalışanı yaşam döngüsü etkinliklerini dinlemek için basit bir arayüz sağlar.
Kitaplık, arka planda updatefound ve statechange gibi istemci tarafı API'leri kullanır ve workbox-window nesnesinde daha üst düzey etkinlik dinleyicileri sağlayarak kullanıcının bu etkinlikleri kullanmasını kolaylaştırır.
Aşağıdaki sayfa kodu, hizmet çalışanının yeni bir sürümü her yüklendiğinde bunu algılamanızı sağlar. Böylece, kullanıcıya bu durumu bildirebilirsiniz:
const wb = new Workbox('/sw.js');
wb.addEventListener('installed', (event) => {
if (event.isUpdate) {
// Show "Update App" banner
}
});
wb.register();
Sayfayı, önbellek verilerindeki değişiklikler hakkında bilgilendirme
Workbox paketi,
workbox-broadcast-update
pencere istemcilerine, önbelleğe alınmış bir yanıtın güncellendiğini bildirmek için standart bir yöntem sunar. Bu, en çok tercih edilen StaleWhileRevalidate stratejisiyle birlikte kullanılır.
Güncellemeleri yayınlamak için hizmet çalışanı tarafındaki strateji seçeneklerinize bir broadcastUpdate.BroadcastUpdatePlugin ekleyin:
import {registerRoute} from 'workbox-routing';
import {StaleWhileRevalidate} from 'workbox-strategies';
import {BroadcastUpdatePlugin} from 'workbox-broadcast-update';
registerRoute(
({url}) => url.pathname.startsWith('/api/'),
new StaleWhileRevalidate({
plugins: [
new BroadcastUpdatePlugin(),
],
})
);
Web uygulamanızda bu etkinlikleri aşağıdaki gibi dinleyebilirsiniz:
navigator.serviceWorker.addEventListener('message', async (event) => {
// Optional: ensure the message came from workbox-broadcast-update
if (event.data.meta === 'workbox-broadcast-update') {
const {cacheName, updatedUrl} = event.data.payload;
// Do something with cacheName and updatedUrl.
// For example, get the cached content and update
// the content on the page.
const cache = await caches.open(cacheName);
const updatedResponse = await cache.match(updatedUrl);
const updatedText = await updatedResponse.text();
}
});
Tarayıcı API'lerini kullanma
Workbox'ın sağladığı işlevsellik ihtiyaçlarınız için yeterli değilse "yayın güncellemeleri" uygulamak için aşağıdaki tarayıcı API'lerini kullanın:
Broadcast Channel API
Hizmet çalışanı bir BroadcastChannel
nesnesi oluşturur ve bu nesneye mesaj göndermeye başlar. Bu mesajları almak isteyen herhangi bir bağlam (ör. sayfa), BroadcastChannel nesnesi oluşturabilir ve mesajları almak için bir mesaj işleyici uygulayabilir.
Yeni bir hizmet çalışanı yüklendiğinde sayfayı bilgilendirmek için aşağıdaki kodu kullanın:
// Create Broadcast Channel to send messages to the page
const broadcast = new BroadcastChannel('sw-update-channel');
self.addEventListener('install', function (event) {
// Inform the page every time a new service worker is installed
broadcast.postMessage({type: 'CRITICAL_SW_UPDATE'});
});
Sayfa, sw-update-channel öğesine abone olarak bu etkinlikleri dinler:
// Create Broadcast Channel and listen to messages sent to it
const broadcast = new BroadcastChannel('sw-update-channel');
broadcast.onmessage = (event) => {
if (event.data && event.data.type === 'CRITICAL_SW_UPDATE') {
// Show "update to refresh" banner to the user.
}
};
Bu basit bir tekniktir ancak sınırlaması tarayıcı desteğidir: Bu yazı yazıldığı sırada Safari bu API'yi desteklemiyordu.
Client API
Client API, Client nesnelerinden oluşan bir dizide yineleme yaparak hizmet çalışanından birden fazla istemciyle iletişim kurmanın basit bir yolunu sunar.
En son odaklanılan sekmeye mesaj göndermek için aşağıdaki hizmet çalışanı kodunu kullanın:
// Obtain an array of Window client objects
self.clients.matchAll(options).then(function (clients) {
if (clients && clients.length) {
// Respond to last focused tab
clients[0].postMessage({type: 'MSG_ID'});
}
});
Sayfada, bu mesajları yakalamak için bir mesaj işleyici uygulanıyor:
// Listen to messages
navigator.serviceWorker.onmessage = (event) => {
if (event.data && event.data.type === 'MSG_ID') {
// Process response
}
};
Client API, bilgileri birden fazla etkin sekmeye yayınlama gibi durumlar için mükemmel bir seçenektir. API, tüm büyük tarayıcılar tarafından desteklenir ancak yöntemlerinin tümü desteklenmez. Kullanmadan önce tarayıcı desteğini kontrol edin.
Mesaj Kanalı
Message Channel, sayfa ile hizmet çalışanı arasında bir iletişim kanalı oluşturmak için sayfadan hizmet çalışanına bir bağlantı noktası ileterek ilk yapılandırma adımını gerektirir. Sayfa bir MessageChannel nesnesi oluşturur ve postMessage() arayüzü aracılığıyla hizmet çalışanına bir bağlantı noktası iletir:
const messageChannel = new MessageChannel();
// Init port
navigator.serviceWorker.controller.postMessage({type: 'PORT_INITIALIZATION'}, [
messageChannel.port2,
]);
Sayfa, bu bağlantı noktasında bir "onmessage" işleyicisi uygulayarak mesajları dinler:
// Listen to messages
messageChannel.port1.onmessage = (event) => {
// Process message
};
Hizmet çalışanı bağlantı noktasını alır ve bağlantı noktasına bir referans kaydeder:
// Initialize
let communicationPort;
self.addEventListener('message', (event) => {
if (event.data && event.data.type === 'PORT_INITIALIZATION') {
communicationPort = event.ports[0];
}
});
Bu noktadan itibaren, bağlantı noktasına referans verirken postMessage() çağrılarak sayfaya mesaj gönderilebilir:
// Communicate
communicationPort.postMessage({type: 'MSG_ID' });
MessageChannel, bağlantı noktalarının başlatılması gerektiğinden uygulaması daha karmaşık olabilir ancak tüm büyük tarayıcılar tarafından desteklenir.
Sonraki adımlar
Bu kılavuzda, Window ile hizmet çalışanı iletişimiyle ilgili belirli bir durumu, yani "yayın güncellemeleri" konusunu ele aldık. İncelenen örnekler arasında önemli hizmet çalışanı yaşam döngüsü etkinliklerini dinleme ve içerikteki veya önbelleğe alınmış verilerdeki değişiklikler hakkında sayfayla iletişim kurma yer alıyor. Hizmet çalışanının daha önce herhangi bir mesaj almadan sayfayla proaktif olarak iletişim kurduğu daha ilginç kullanım alanları düşünebilirsiniz.
Pencere ve hizmet çalışanı iletişimiyle ilgili daha fazla kalıp için şunlara göz atın:
- Zorunlu önbelleğe alma kılavuzu: Kaynakları önceden önbelleğe almak için sayfadan bir hizmet çalışanı çağırma (ör. önceden getirme senaryolarında).
- İki yönlü iletişim: Bir görevi (ör. büyük bir indirme işlemi) bir hizmet çalışanına devretme ve sayfanın ilerleme durumu hakkında bilgilendirilmesini sağlama.