Bazı durumlarda, hizmet çalışanının belirli bir etkinlik hakkında bilgi vermek için kontrol ettiği etkin sekmelerden herhangi biriyle 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.
- "Uygulama artık çevrimdışı çalışmaya hazır" veya "İçeriğin yeni sürümü kullanıma sunuldu" gibi bir gösterge göstererek kullanıcıya hizmet çalışanı tarafında önbelleğe alınmış verilerde yapılan bir değişiklik hakkında bilgi verin.
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 ile hizmet çalışanları arasında bu tür bir iletişimi uygulamanın farklı yollarını 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 sayede, yeni bir hizmet çalışanı devreye girdiğinde kullanıcılara "Güncelleme Var" banner'ı gösterilir. Böylece kullanıcılar PWA'yı yenileyebilir ve en yeni ö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 haberdar eder:
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.
Kitaplık, updatefound
ve statechange gibi istemci tarafı API'leri kullanır ve workbox-window
nesnesinde daha üst düzey etkinlik dinleyicileri sağlar. Böylece kullanıcının bu etkinlikleri kullanması kolaylaşı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ı önbelleğe alınan verilerdeki 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 tarayıcıyı destekleme sınırlaması vardır: Bu makalenin yazıldığı sırada Safari bu API'yi desteklemiyor.
Client API
İstemci API'si, bir dizi Client
nesnesi üzerinde iterasyon yaparak hizmet işçisinden birden fazla istemciyle iletişim kurmanın basit bir yolunu sunar.
Son odaklanan 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'});
}
});
Sayfa, bu mesajları engellemek 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ı, sayfadan hizmet işleyiciye bir bağlantı noktası aktararak aralarında bir iletişim kanalı oluşturmak için ilk yapılandırma adımı 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ş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' });
MessageChannel
, bağlantı noktalarını başlatma ihtiyacı nedeniyle uygulamak daha karmaşık olabilir ancak tüm büyük 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şimi için daha fazla kalıp görmek isterseniz:
- 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.