Dalam beberapa skenario, pekerja layanan mungkin perlu berkomunikasi secara proaktif dengan tab aktif mana pun yang dikontrolnya untuk menginformasikan peristiwa tertentu. Contohnya mencakup:
- Memberi tahu halaman saat versi baru pekerja layanan telah diinstal, sehingga halaman dapat menampilkan tombol "Update untuk memuat ulang" kepada pengguna untuk segera mengakses fungsi baru.
- Memberi tahu pengguna tentang perubahan pada data cache yang terjadi di sisi pekerja layanan, dengan menampilkan indikasi, seperti: "Aplikasi sekarang siap untuk bekerja offline", atau "Versi baru konten tersedia".
Kita akan menyebut jenis kasus penggunaan ini ketika pekerja layanan tidak perlu menerima pesan dari halaman untuk memulai komunikasi sebagai "broadcast update". Dalam panduan ini, kita akan meninjau berbagai cara dalam menerapkan jenis komunikasi ini antara halaman dan pekerja layanan, menggunakan API browser standar dan library Workbox.
Kasus produksi
Tinder
PWA Tinder menggunakan workbox-window
untuk memproses momen siklus proses pekerja layanan yang penting dari halaman ("diinstal", "dikontrol", dan "diaktifkan"). Dengan begitu, saat pekerja layanan baru muncul, banner "Update Tersedia" akan ditampilkan, sehingga pengguna dapat memuat ulang PWA dan mengakses fitur terbaru:
Pirus
Di Squoosh PWA, setelah pekerja layanan meng-cache semua aset yang diperlukan agar dapat berfungsi secara offline, pekerja layanan akan mengirim pesan ke halaman untuk menampilkan toast "Siap bekerja secara offline", yang memberi tahu pengguna tentang fitur ini:
Menggunakan Workbox
Memproses peristiwa siklus proses pekerja layanan
workbox-window
menyediakan antarmuka yang mudah untuk memproses peristiwa siklus proses pekerja layanan
yang penting.
Di balik layar, library ini menggunakan API sisi klien seperti updatefound
dan statechange serta menyediakan pemroses peristiwa dengan level yang lebih tinggi dalam objek workbox-window
, sehingga memudahkan pengguna menggunakan peristiwa ini.
Kode halaman berikut memungkinkan Anda mendeteksi setiap kali pekerja layanan versi baru diinstal, sehingga Anda dapat menyampaikannya kepada pengguna:
const wb = new Workbox('/sw.js');
wb.addEventListener('installed', (event) => {
if (event.isUpdate) {
// Show "Update App" banner
}
});
wb.register();
Memberi tahu halaman tentang perubahan data cache
Paket Workbox
workbox-broadcast-update
menyediakan cara standar untuk memberi tahu klien jendela bahwa respons yang di-cache telah diperbarui. Ini
paling sering digunakan bersama dengan strategi
StaleWhileRevalidate.
Untuk menyiarkan update, tambahkan broadcastUpdate.BroadcastUpdatePlugin
ke opsi strategi Anda di
sisi pekerja layanan:
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(),
],
})
);
Di aplikasi web, Anda dapat memproses peristiwa ini seperti berikut:
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();
}
});
Menggunakan API browser
Jika fungsi yang disediakan Workbox tidak cukup untuk kebutuhan Anda, gunakan API browser berikut untuk mengimplementasikan "broadcast update":
API Saluran Siaran
Pekerja layanan membuat objek BroadcastChannel dan mulai mengirim pesan ke objek tersebut. Semua konteks (misalnya halaman) yang tertarik untuk menerima pesan ini dapat membuat instance objek BroadcastChannel
dan menerapkan pengendali pesan untuk menerima pesan.
Untuk memberi tahu halaman saat pekerja layanan baru diinstal, gunakan kode berikut:
// 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'});
});
Halaman memproses peristiwa ini dengan berlangganan sw-update-channel
:
// 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.
}
};
Ini adalah teknik sederhana, tetapi batasannya adalah dukungan browser: pada saat tulisan ini ditulis, Safari tidak mendukung API ini.
Client API
Client API menyediakan cara yang mudah
untuk berkomunikasi dengan beberapa klien dari pekerja layanan dengan melakukan iterasi melalui array
objek Client
.
Gunakan kode pekerja layanan berikut untuk mengirim pesan ke tab yang terakhir difokuskan:
// 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'});
}
});
Halaman tersebut menerapkan pengendali pesan untuk menangkap pesan berikut:
// Listen to messages
navigator.serviceWorker.onmessage = (event) => {
if (event.data && event.data.type === 'MSG_ID') {
// Process response
}
};
API Klien adalah opsi yang bagus untuk kasus-kasus seperti menyiarkan informasi ke beberapa tab aktif. API ini didukung oleh semua browser utama, tetapi tidak semua metodenya. Periksa dukungan browser sebelum menggunakannya.
Saluran Pesan
Message Channel memerlukan langkah konfigurasi awal, dengan meneruskan port dari halaman ke pekerja layanan, untuk membuat saluran komunikasi di antara keduanya. Halaman akan membuat instance objek MessageChannel
dan meneruskan
port ke pekerja layanan, melalui antarmuka postMessage()
:
const messageChannel = new MessageChannel();
// Init port
navigator.serviceWorker.controller.postMessage({type: 'PORT_INITIALIZATION'}, [
messageChannel.port2,
]);
Halaman ini memproses pesan dengan menerapkan pengendali "onmessage" pada port tersebut:
// Listen to messages
messageChannel.port1.onmessage = (event) => {
// Process message
};
Pekerja layanan menerima port dan menyimpan referensi ke port tersebut:
// Initialize
let communicationPort;
self.addEventListener('message', (event) => {
if (event.data && event.data.type === 'PORT_INITIALIZATION') {
communicationPort = event.ports[0];
}
});
Dari saat itu, kode ini dapat mengirim pesan ke halaman, dengan memanggil postMessage()
dalam referensi ke port:
// Communicate
communicationPort.postMessage({type: 'MSG_ID' });
MessageChannel
mungkin lebih kompleks untuk diterapkan karena perlu menginisialisasi port, tetapi didukung oleh semua browser utama.
Langkah berikutnya
Dalam panduan ini, kami mempelajari satu kasus tertentu komunikasi Window ke pekerja layanan: "broadcast update". Contoh yang dipelajari mencakup memproses peristiwa siklus proses pekerja layanan yang penting, dan menyampaikan perubahan dalam konten atau data yang di-cache ke halaman. Anda dapat memikirkan kasus penggunaan yang lebih menarik di mana pekerja layanan berkomunikasi secara proaktif dengan halaman, tanpa menerima pesan apa pun sebelumnya.
Untuk pola komunikasi Window dan pekerja layanan lainnya, lihat:
- Panduan penyimpanan cache implisit: Memanggil pekerja layanan dari halaman untuk meng-cache resource terlebih dahulu (mis. dalam skenario pengambilan data).
- Komunikasi dua arah: Mendelegasikan tugas ke pekerja layanan (misalnya, download yang berat), dan terus memberi tahu halaman tentang progresnya.