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 oleh pekerja layanan saat ini harus ditutup atau menjalani navigasi sebelum pekerja layanan yang diupdate diaktifkan dan mengambil kontrol.

Dalam banyak kasus, mungkin tidak masalah untuk membiarkan hal ini terjadi tepat waktu, tetapi dalam beberapa kasus, Anda dapat memberi tahu pengguna bahwa ada update pekerja layanan yang tertunda, lalu mengotomatiskan proses pengalihan ke pekerja layanan baru. Untuk melakukannya, Anda harus menambahkan beberapa kode di halaman, dan pekerja layanan.

Kode yang akan dimasukkan ke halaman

Kode berikut berjalan di elemen <script> inline menggunakan modul JavaScript yang diimpor dari versi workbox-window yang dihosting CDN. Layanan ini mendaftarkan pekerja layanan menggunakan workbox-window, dan akan bereaksi jika pekerja layanan terhenti dalam fase menunggu. Saat pekerja layanan yang menunggu ditemukan, kode ini memberi tahu pengguna bahwa versi terbaru situs 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 menerima, messageSkipWaiting() akan memberi tahu pekerja layanan yang menunggu untuk memanggil self.skipWaiting(), yang berarti pekerja layanan akan mulai diaktifkan. Setelah diaktifkan, pekerja layanan baru akan mengontrol setiap klien yang ada, sehingga memicu peristiwa controlling di workbox-window. Jika hal ini terjadi, halaman saat ini akan dimuat ulang menggunakan versi terbaru dari semua aset yang di-cache dan logika perutean baru yang ditemukan dalam pekerja layanan yang 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 memungkinkannya mengetahui kapan harus melewati fase menunggu. Jika menggunakan generateSW dari workbox-build dan opsi skipWaiting ditetapkan ke false (default), Anda dapat memulai, karena kode di bawah akan secara otomatis disertakan dalam file pekerja layanan yang dihasilkan.

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

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

Fungsi ini akan memproses pesan yang dikirim ke pekerja layanan dari workbox-window dengan nilai type sebesar SKIP_WAITING, dan ketika hal itu terjadi, memanggil self.skipWaiting(). Metode messageSkipWaiting() di workbox-window, yang ditampilkan di 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 ketika kegagalan dalam memberikan kesempatan untuk memuat ulang halaman saat update pekerja layanan dapat menyebabkan perilaku yang tidak terduga. Tidak ada aturan yang tegas dan cepat mengenai apakah Anda harus menampilkan perintah muat ulang atau tidak, tetapi berikut adalah beberapa situasi yang mungkin logis:

  • Anda menggunakan precache secara ekstensif. Jika menyangkut aset statis, Anda dapat mengalami masalah nanti jika menggunakan strategi yang mengutamakan jaringan atau strategi khusus jaringan untuk permintaan navigasi, tetapi menjalankan lambat pada aset statis. Hal ini bisa menyebabkan situasi saat aset berversi dapat berubah, dan pekerja layanan belum melakukan precache-nya. Menawarkan tombol muat ulang di sini dapat menghindari beberapa perilaku yang tidak diharapkan.
  • Jika Anda menayangkan HTML yang telah di-precache. Dalam hal ini, Anda harus sangat mempertimbangkan penawaran tombol muat ulang pada update pekerja layanan, karena update pada HTML tersebut tidak akan dikenali sampai pekerja layanan yang diupdate mengambil alih kontrol.
  • Jika Anda tidak terlalu mengandalkan cache runtime. Saat meng-cache resource saat runtime, Anda tidak perlu memberi tahu pengguna bahwa mereka harus memuat ulang. Saat aset berversi berubah, aset tersebut akan ditambahkan ke cache runtime pada waktunya—dengan asumsi bahwa permintaan navigasi menggunakan strategi yang mengutamakan jaringan atau hanya jaringan.
  • Saat menggunakan strategi buang saat validasi ulang, Anda dapat mempertimbangkan untuk menggunakan modul workbox-broadcast-update untuk memberi tahu pengguna tentang pembaruan pekerja layanan.

Perlu atau tidaknya Anda memberi tahu pengguna tentang pembaruan ke pekerja layanan, bergantung pada aplikasi Anda, dan persyaratan uniknya. Jika Anda mendapati bahwa pengguna mengalami perilaku aneh saat Anda menerapkan pekerja layanan baru, hal itu mungkin merupakan sinyal terbaik yang harus Anda beri tahu mereka.