Bazı senaryolarda Service Worker'ın, belirli bir olay hakkında bilgi vermek için kontrol ettiği etkin sekmelerle proaktif olarak iletişim kurması gerekebilir. Örnekler:
- Hizmet çalışanının yeni bir sürümü yüklendiğinde sayfayı bilgilendirerek sayfanın, kullanıcıya yeni işleve hemen erişmesi için "Yenilemek için güncelle" düğmesi gösterebilmesi.
- Service Worker tarafında önbelleğe alınan verilerde meydana gelen değişiklik hakkında kullanıcıyı bilgilendirir. Bunun 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üleyebilir.
Hizmet çalışanının iletişim başlatmak için sayfadan mesaj alması gerekmeyen bu tür kullanım alanlarına "yayın güncellemeleri" adını vereceğiz. Bu kılavuzda, standart tarayıcı API'lerini ve Workbox kitaplığını kullanarak sayfalar ve hizmet çalışanları arasında bu tür bir iletişimi uygulamanın farklı yöntemlerini inceleyeceğiz.
Üretim durumları
Tinder
Tinder PWA, sayfadaki önemli hizmet çalışanı yaşam döngüsü anlarını ("yüklendi", "denetlendi" ve "etkinleştirildi") dinlemek için workbox-window
kullanır. Bu şekilde, yeni bir hizmet çalışanı söz konusu olduğunda bir "Güncelleme Mevcut" banner'ı gösterir. Böylece çalışan PWA'yı yenileyebilir ve en son özelliklere erişebilir:
Squoosh
Squoosh PWA'da hizmet çalışanı, uygulamanın çevrimdışı çalışmasını sağlamak için gerekli tüm öğeleri önbelleğe aldığında sayfaya bir mesaj göndererek "Çevrimdışı çalışmaya hazır" bildirimini gösterir ve kullanıcıya bu özellikten bahseder:
Workbox'u kullanma
Hizmet çalışanı 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.
Temelde kitaplık, updatefound
ve statechange gibi istemci tarafı API'leri kullanır ve workbox-window
nesnesinde daha üst düzey etkinlik işleyiciler sağlayarak kullanıcının bu etkinlikleri tüketmesini 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ıza olanak tanır. Böylece, bunu kullanıcıya 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 paketiworkbox-broadcast-update
pencere istemcilerini, önbelleğe alınmış bir yanıtın güncellendiği konusunda bilgilendirmenin standart bir yolunu sağlar. Bu strateji, genellikle 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'un sağladığı işlevler ihtiyaçlarınıza yetmiyorsa "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 tüm bağlamlar (ör. sayfa), bir 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
'ye 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 bununla ilgili sınırlama, tarayıcı desteğidir: Bu yazı yazıldığında Safari bu API'yi desteklememektedir.
İstemci API'si
İstemci API'si, bir dizi Client
nesnesi üzerinde iterasyon yaparak hizmet işçisinden birden fazla istemciyle iletişim kurmanın basit bir yolunu sağlar.
Odaklanılan son sekmeye mesaj göndermek için aşağıdaki Service Worker 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'});
}
});
Sayfa, bu mesajları durdurmak için bir mesaj işleyici uygular:
// Listen to messages
navigator.serviceWorker.onmessage = (event) => {
if (event.data && event.data.type === 'MSG_ID') {
// Process response
}
};
İstemci API'si, birden fazla etkin sekmede bilgi yayınlama gibi durumlar için mükemmel bir seçenektir. API, tüm büyük tarayıcılar tarafından desteklenir ancak API'nin tüm yöntemleri desteklenmez. Kullanmadan önce tarayıcı desteğini kontrol edin.
Mesaj Kanalı
Mesaj Kanalı, aralarında bir iletişim kanalı oluşturmak için sayfadan hizmet çalışanına bir bağlantı noktası geçirerek 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ına bir "onmessage" işleyici 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 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 olarak postMessage()
çağrılarak sayfaya mesaj gönderilebilir:
// Communicate
communicationPort.postMessage({type: 'MSG_ID' });
Bağlantı noktalarının başlatılması gerektiği için MessageChannel
ürününün uygulanması daha karmaşık olabilir ancak tüm önemli tarayıcılar tarafından desteklenir.
Sonraki adımlar
Bu kılavuzda, pencere ile hizmet çalışanı arasındaki iletişimin belirli bir örneğini inceledik: "yayın güncellemeleri". İncelenen örnekler arasında önemli hizmet çalışanı yaşam döngüsü etkinliklerini dinleme ve içerik veya önbelleğe alınmış verilerdeki değişikliklerle ilgili sayfaya iletişim kurma yer alır. 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şimleriyle ilgili diğer kalıplar için aşağıdaki makalelere 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. ön getirme senaryolarında).
- İki yönlü iletişim: Bir görevi servis çalışanına devretme (ör. büyük boyutlu bir indirme) ve sayfayı ilerleme durumu hakkında bilgilendirme.