Menyiarkan pembaruan ke halaman dengan pekerja layanan

Andrew Guan
Andrew Guan
Demián Renzulli
Demián Renzulli

Dalam beberapa skenario, pekerja layanan mungkin perlu berkomunikasi secara proaktif dengan tab aktif yang dikontrolnya untuk memberi tahu 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 mengakses fungsi baru segera.
  • Memberi tahu pengguna tentang perubahan pada data yang di-cache yang terjadi di sisi pekerja layanan, dengan menampilkan indikasi, seperti: "Aplikasi kini siap digunakan secara offline", atau "Versi baru konten tersedia".
Diagram yang menunjukkan pekerja layanan berkomunikasi dengan halaman untuk mengirim update.

Kami akan menyebut jenis kasus penggunaan ini, saat pekerja layanan tidak perlu menerima pesan dari halaman untuk memulai komunikasi, sebagai "pembaruan siaran". Dalam panduan ini, kita akan meninjau berbagai cara untuk menerapkan jenis komunikasi ini antara halaman dan pekerja layanan, dengan 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 mulai digunakan, banner "Update Tersedia" akan ditampilkan, sehingga pengguna dapat memuat ulang PWA dan mengakses fitur terbaru:

Screenshot fungsi 'Update Tersedia' aplikasi web Tinder.
Di PWA Tinder, pekerja layanan memberi tahu halaman bahwa versi baru sudah siap, dan halaman menampilkan banner "Update Tersedia" kepada pengguna.

Squoosh

Di PWA Squoosh, saat pekerja layanan telah meng-cache semua aset yang diperlukan agar dapat berfungsi secara offline, pekerja layanan akan mengirim pesan ke halaman untuk menampilkan toast "Siap digunakan secara offline", yang memberi tahu pengguna tentang fitur tersebut:

Screenshot fungsi 'Siap digunakan secara offline' aplikasi web Squoosh.
Di PWA Squoosh, pekerja layanan menyiarkan update ke halaman saat cache siap, dan halaman menampilkan toast "Siap digunakan secara offline".

Menggunakan Workbox

Memproses peristiwa siklus proses pekerja layanan

workbox-window menyediakan antarmuka langsung untuk memproses peristiwa siklus proses pekerja layanan penting. Di balik layar, library menggunakan API sisi klien seperti updatefound dan statechange serta menyediakan pemroses peristiwa tingkat yang lebih tinggi dalam objek workbox-window, sehingga memudahkan pengguna untuk menggunakan peristiwa ini.

Kode halaman berikut memungkinkan Anda mendeteksi setiap kali versi baru pekerja layanan diinstal, sehingga Anda dapat mengomunikasikannya 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. Hal 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 menerapkan "update siaran":

Broadcast Channel API

Service worker membuat objek BroadcastChannel dan mulai mengirim pesan ke objek tersebut. Konteks apa pun (misalnya, halaman) yang tertarik untuk menerima pesan ini dapat membuat instance objek BroadcastChannel dan menerapkan pemroses 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 penulisan ini, Safari tidak mendukung API ini.

Client API

Client API menyediakan cara yang mudah untuk berkomunikasi dengan beberapa klien dari pekerja layanan dengan melakukan iterasi pada array objek Client.

Gunakan kode service worker 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 menerapkan pengendali pesan untuk mencegat pesan ini:

// Listen to messages
navigator.serviceWorker.onmessage = (event) => {
     if (event.data && event.data.type === 'MSG_ID') {
         // Process response
   }
};

Client API adalah opsi yang bagus untuk kasus seperti menyiarkan informasi ke beberapa tab aktif. API 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 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 memproses pesan dengan menerapkan pengendali "onmessage" di port tersebut:

// Listen to messages
messageChannel.port1.onmessage = (event) => {
  // Process message
};

Service worker 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];
  }
});

Mulai saat itu, aplikasi dapat mengirim pesan ke halaman dengan memanggil postMessage() dalam referensi ke port:

// Communicate
communicationPort.postMessage({type: 'MSG_ID' });

MessageChannel mungkin lebih rumit untuk diterapkan, karena perlu menginisialisasi port, tetapi didukung oleh semua browser utama.

Langkah berikutnya

Dalam panduan ini, kita telah mempelajari satu kasus khusus komunikasi Window ke pekerja layanan: "broadcast updates". Contoh yang dieksplorasi mencakup memproses peristiwa siklus proses penting pekerja layanan, dan berkomunikasi dengan halaman tentang perubahan konten atau data yang di-cache. Anda dapat memikirkan kasus penggunaan yang lebih menarik saat pekerja layanan berkomunikasi secara proaktif dengan halaman, tanpa menerima pesan apa pun sebelumnya.

Untuk mengetahui pola komunikasi Window dan pekerja layanan lainnya, lihat:

  • Panduan caching imperatif: Memanggil pekerja layanan dari halaman untuk melakukan cache resource terlebih dahulu (misalnya, dalam skenario pengambilan data terlebih dahulu).
  • Komunikasi dua arah: Mendelegasikan tugas ke pekerja layanan (misalnya, download besar), dan terus memberi tahu halaman tentang progresnya.

Referensi lainnya