Menangani update pekerja layanan dengan segera

Secara default, siklus proses pekerja layanan mengharuskan saat pekerja layanan yang diupdate ditemukan dan diinstal, semua tab terbuka yang dikontrol pekerja layanan saat ini harus ditutup atau menjalani navigasi sebelum pekerja layanan yang diupdate diaktifkan dan mengambil kontrol.

Dalam banyak kasus, tidak apa-apa jika Anda membiarkan hal ini terjadi pada waktunya, tetapi dalam beberapa kasus, Anda mungkin ingin memberi tahu pengguna bahwa ada update pekerja layanan yang tertunda, lalu mengotomatiskan proses peralihan ke pekerja layanan yang baru. Untuk melakukannya, Anda harus menambahkan beberapa kode di halaman dan pekerja layanan Anda.

Kode yang akan dimasukkan ke halaman

Kode berikut berjalan dalam elemen <script> inline menggunakan modul JavaScript yang diimpor dari versi workbox-window yang dihosting CDN. Tindakan ini mendaftarkan pekerja layanan menggunakan workbox-window, dan akan bereaksi jika pekerja layanan terjebak dalam fase tunggu. Saat pekerja layanan yang menunggu ditemukan, kode ini memberi tahu pengguna bahwa versi situs yang diperbarui telah tersedia dan meminta mereka untuk memuat ulang.

<!-- This script tag uses JavaScript modules, so the proper `type` attribute value is required -->
<script type="module">
  // This code sample uses features introduced in Workbox v6.
  import {Workbox} from 'https://storage.googleapis.com/workbox-cdn/releases/6.4.1/workbox-window.prod.mjs';

  if ('serviceWorker' in navigator) {
    const wb = new Workbox('/sw.js');
    let registration;

    const showSkipWaitingPrompt = async (event) => {
      // Assuming the user accepted the update, set up a listener
      // that will reload the page as soon as the previously waiting
      // service worker has taken control.
      wb.addEventListener('controlling', () => {
        // At this point, reloading will ensure that the current
        // tab is loaded under the control of the new service worker.
        // Depending on your web app, you may want to auto-save or
        // persist transient state before triggering the reload.
        window.location.reload();
      });

      // When `event.wasWaitingBeforeRegister` is true, a previously
      // updated service worker is still waiting.
      // You may want to customize the UI prompt accordingly.

      // This code assumes your app has a promptForUpdate() method,
      // which returns true if the user wants to update.
      // Implementing this is app-specific; some examples are:
      // https://open-ui.org/components/alert.research or
      // https://open-ui.org/components/toast.research
      const updateAccepted = await promptForUpdate();

      if (updateAccepted) {
        wb.messageSkipWaiting();
      }
    };

    // Add an event listener to detect when the registered
    // service worker has installed but is waiting to activate.
    wb.addEventListener('waiting', (event) => {
      showSkipWaitingPrompt(event);
    });

    wb.register();
  }
</script>

Jika diterima, messageSkipWaiting() akan memberi tahu pekerja layanan yang menunggu untuk memanggil self.skipWaiting(), yang berarti layanan akan mulai diaktifkan. Setelah diaktifkan, pekerja layanan baru akan mengontrol klien yang ada, sehingga memicu peristiwa controlling di workbox-window. Jika hal ini terjadi, halaman saat ini akan dimuat ulang menggunakan versi terbaru semua aset yang telah di-pra-cache dan logika perutean baru yang ditemukan di pekerja layanan yang telah diupdate.

Kode yang akan dimasukkan ke dalam pekerja layanan

Setelah mendapatkan kode dari bagian sebelumnya di halaman, Anda harus menambahkan beberapa kode ke pekerja layanan yang memberi tahu kapan harus melewati tahap menunggu. Jika Anda menggunakan generateSW dari workbox-build dan opsi skipWaiting-nya ditetapkan ke false (default), Anda siap memulai, karena kode di bawah ini akan otomatis disertakan dalam file pekerja layanan yang dihasilkan.

Jika menulis pekerja layanan sendiri—mungkin bersama dengan salah satu alat build Workbox dalam mode injectManifest—Anda harus menambahkan sendiri kode berikut:

addEventListener('message', (event) => {
  if (event.data && event.data.type === 'SKIP_WAITING') {
    self.skipWaiting();
  }
});

Tindakan ini akan memproses pesan yang dikirim ke pekerja layanan dari workbox-window dengan nilai type SKIP_WAITING, dan jika hal itu terjadi, memanggil self.skipWaiting(). Metode messageSkipWaiting() di workbox-window, yang ditampilkan dalam contoh kode sebelumnya, bertanggung jawab untuk mengirim pesan ini.

Apakah Anda perlu menampilkan perintah?

Ini bukanlah pola yang harus diikuti oleh setiap aplikasi yang men-deploy pekerja layanan. Ini untuk skenario tertentu saat kegagalan dalam memberikan kesempatan untuk memuat ulang halaman pada update pekerja layanan dapat menyebabkan perilaku yang tidak terduga. Tidak ada aturan baku dan cepat mengenai apakah Anda harus menampilkan prompt muat ulang, tetapi berikut beberapa situasi yang mungkin relevan:

  • Anda menggunakan precache secara ekstensif. Jika aset statis terkait, Anda dapat mengalami masalah di kemudian hari jika menggunakan strategi yang mengutamakan jaringan atau khusus jaringan untuk permintaan navigasi, tetapi lambat memuat aset statis. Hal ini dapat menyebabkan situasi saat aset berversi dapat berubah, dan pekerja layanan belum melakukan pra-cache terhadap aset tersebut. Menawarkan tombol muat ulang di sini dapat menghindari beberapa perilaku yang tidak terduga.
  • Jika Anda menyajikan HTML yang telah dipra-cache. Dalam kasus ini, Anda harus sangat mempertimbangkan untuk menawarkan tombol muat ulang pada pembaruan pekerja layanan, karena pembaruan pada HTML tersebut tidak akan dikenali hingga pekerja layanan yang diperbarui mengambil kontrol.
  • Jika Anda tidak terlalu mengandalkan caching runtime. Saat meng-cache resource saat runtime, Anda tidak perlu memberi tahu pengguna bahwa resource harus dimuat ulang. Saat aset berversi berubah, aset tersebut akan ditambahkan ke cache runtime pada waktunya—dengan asumsi permintaan navigasi menggunakan strategi yang mengutamakan jaringan atau khusus jaringan.
  • Saat menggunakan strategi stale-temporary-revalidate, Anda dapat mempertimbangkan untuk menggunakan modul workbox-broadcast-update untuk memberi tahu pengguna tentang info terbaru pekerja layanan.

Perlu atau tidaknya Anda memberi tahu pengguna tentang update pekerja layanan, bergantung pada aplikasi Anda, dan persyaratan uniknya. Jika Anda menemukan bahwa pengguna mengalami perilaku aneh saat Anda mendorong pekerja layanan baru, itu mungkin sinyal terbaik agar Anda memberi tahu mereka.