Masa pakai pekerja layanan

Sulit untuk mengetahui apa yang dilakukan pekerja layanan tanpa memahami siklus hidup mereka. Cara kerja bagian dalam mereka akan tampak buram, bahkan acak. Perlu diingat bahwa—seperti API browser lainnya—perilaku pekerja layanan terdefinisi dengan baik, ditentukan, dan memungkinkan aplikasi offline, sekaligus memfasilitasi update tanpa mengganggu pengalaman pengguna.

Sebelum mendalami Workbox, penting untuk memahami siklus proses pekerja layanan sehingga yang dimaksud dengan Workbox.

Menentukan istilah

Sebelum masuk ke siklus proses pekerja layanan, ada baiknya menentukan beberapa istilah tentang cara siklus proses tersebut beroperasi.

Kontrol dan cakupan

Gagasan mengenai kontrol sangat penting untuk memahami cara pekerja layanan beroperasi. Halaman yang dideskripsikan sebagai dikontrol oleh pekerja layanan adalah halaman yang memungkinkan pekerja layanan menangkap permintaan jaringan atas namanya. Pekerja layanan ada dan dapat melakukan tugas untuk halaman dalam cakupan tertentu.

Cakupan

Cakupan pekerja layanan ditentukan oleh lokasinya di server web. Jika pekerja layanan berjalan di halaman yang terletak di /subdir/index.html, dan berada di /subdir/sw.js, cakupan pekerja layanan adalah /subdir/. Untuk melihat konsep penerapan konsep, lihat contoh ini:

  1. Buka https://service-worker-scope-viewer.glitch.me/subdir/index.html. Pesan yang mengatakan tidak ada pekerja layanan mengontrol halaman akan muncul. Namun, halaman tersebut mendaftarkan pekerja layanan dari https://service-worker-scope-viewer.glitch.me/subdir/sw.js.
  2. Muat ulang halaman. Karena telah terdaftar dan sekarang aktif, pekerja layanan akan mengontrol halaman. Formulir yang berisi cakupan pekerja layanan, status saat ini, dan URL-nya akan terlihat. Catatan: keharusan memuat ulang halaman tidak ada hubungannya dengan cakupan, melainkan siklus proses pekerja layanan, yang akan dijelaskan nanti.
  3. Sekarang, buka https://service-worker-scope-viewer.glitch.me/index.html. Meskipun pekerja layanan terdaftar di asal ini, masih ada pesan yang mengatakan bahwa tidak ada pekerja layanan saat ini. Hal tersebut dikarenakan halaman ini tidak berada dalam cakupan pekerja layanan terdaftar.

Cakupan membatasi halaman yang dikontrol oleh pekerja layanan. Dalam contoh ini, pekerja layanan yang dimuat dari /subdir/sw.js hanya dapat mengontrol halaman yang berada di /subdir/ atau subhierarkinya.

Di atas adalah cara kerja pencakupan secara default, tetapi cakupan maksimum yang diizinkan dapat diganti dengan menyetel header respons Service-Worker-Allowed, serta meneruskan opsi scope ke metode register.

Kecuali ada alasan kuat untuk membatasi cakupan pekerja layanan ke subset origin, muat pekerja layanan dari direktori utama server web sehingga cakupannya seluas mungkin, dan jangan khawatir dengan header Service-Worker-Allowed. jauh lebih mudah bagi semua orang dengan cara itu.

Klien

Ketika dikatakan bahwa pekerja layanan mengontrol halaman, berarti itu benar-benar mengontrol klien. Klien adalah halaman terbuka yang URL-nya termasuk dalam cakupan pekerja layanan tersebut. Secara khusus, ini adalah instance WindowClient.

Siklus proses pekerja layanan baru

Agar pekerja layanan dapat mengontrol halaman, halaman tersebut harus dibuat terlebih dahulu. Mari kita mulai dengan apa yang terjadi ketika pekerja layanan baru di-deploy untuk situs tanpa pekerja layanan yang aktif.

Pendaftaran

Pendaftaran adalah langkah awal siklus proses pekerja layanan:

<!-- In index.html, for example: -->
<script>
  // Don't register the service worker
  // until the page has fully loaded
  window.addEventListener('load', () => {
    // Is service worker available?
    if ('serviceWorker' in navigator) {
      navigator.serviceWorker.register('/sw.js').then(() => {
        console.log('Service worker registered!');
      }).catch((error) => {
        console.warn('Error registering service worker:');
        console.warn(error);
      });
    }
  });
</script>

Kode ini berjalan di thread utama dan melakukan hal berikut:

  1. Karena kunjungan pertama pengguna ke situs terjadi tanpa pekerja layanan yang terdaftar, tunggu hingga halaman dimuat sepenuhnya sebelum mendaftarkannya. Hal ini akan menghindari pertentangan bandwidth jika pekerja layanan melakukan precache apa pun.
  2. Meskipun pekerja layanan didukung dengan baik, pemeriksaan cepat akan membantu menghindari error di browser yang tidak mendukungnya.
  3. Setelah halaman dimuat sepenuhnya, dan jika pekerja layanan didukung, daftarkan /sw.js.

Beberapa hal penting yang perlu dipahami adalah:

  • Pekerja layanan hanya tersedia melalui HTTPS atau localhost.
  • Jika konten pekerja layanan berisi error sintaksis, pendaftaran akan gagal dan pekerja layanan akan dihapus.
  • Pengingat: pekerja layanan beroperasi dalam cakupan. Di sini, cakupannya adalah seluruh asal, seperti yang dimuat dari direktori root.
  • Saat pendaftaran dimulai, status pekerja layanan disetel ke 'installing'.

Setelah pendaftaran selesai, penginstalan akan dimulai.

Penginstalan

Pekerja layanan mengaktifkan peristiwa install setelah pendaftaran. install hanya dipanggil sekali per pekerja layanan, dan tidak akan diaktifkan lagi sampai diupdate. Callback untuk peristiwa install dapat didaftarkan dalam cakupan pekerja dengan addEventListener:

// /sw.js
self.addEventListener('install', (event) => {
  const cacheKey = 'MyFancyCacheName_v1';

  event.waitUntil(caches.open(cacheKey).then((cache) => {
    // Add all the assets in the array to the 'MyFancyCacheName_v1'
    // `Cache` instance for later use.
    return cache.addAll([
      '/css/global.bc7b80b7.css',
      '/css/home.fe5d0b23.css',
      '/js/home.d3cc4ba4.js',
      '/js/jquery.43ca4933.js'
    ]);
  }));
});

Tindakan ini akan membuat instance Cache baru dan melakukan precache aset. Kita akan memiliki banyak kesempatan untuk membahas precache nanti, jadi mari kita fokus pada peran event.waitUntil. event.waitUntil menerima promise, dan menunggu hingga promise tersebut diselesaikan. Dalam contoh ini, promise tersebut melakukan dua hal asinkron:

  1. Membuat instance Cache baru bernama 'MyFancyCache_v1'.
  2. Setelah cache dibuat, array URL aset akan di-precache menggunakan metode addAll asinkronnya.

Penginstalan akan gagal jika promise yang diteruskan ke event.waitUntil ditolak. Jika hal ini terjadi, pekerja layanan akan dihapus.

Jika promise resolve, penginstalan berhasil dan status pekerja layanan akan berubah menjadi 'installed', lalu akan diaktifkan.

Aktivasi

Jika pendaftaran dan penginstalan berhasil, pekerja layanan akan diaktifkan, dan statusnya menjadi 'activating' Pekerjaan dapat dilakukan selama aktivasi di peristiwa activate pekerja layanan. Tugas umum dalam peristiwa ini adalah memangkas cache lama, tetapi untuk pekerja layanan baru, hal ini tidak relevan untuk saat ini, dan akan diperluas saat kita membahas update pekerja layanan.

Untuk pekerja layanan baru, activate diaktifkan segera setelah install berhasil. Setelah aktivasi selesai, status pekerja layanan menjadi 'activated'. Perhatikan bahwa, secara default, pekerja layanan baru tidak akan mulai mengontrol halaman hingga navigasi berikutnya atau pemuatan ulang halaman.

Menangani update pekerja layanan

Setelah pekerja layanan pertama di-deploy, mungkin perlu diupdate nanti. Misalnya, update mungkin diperlukan jika perubahan terjadi dalam logika penanganan permintaan atau precaching.

Kapan update dilakukan

Browser akan memeriksa update pekerja layanan saat:

  • Pengguna membuka halaman dalam cakupan pekerja layanan.
  • navigator.serviceWorker.register() dipanggil dengan URL yang berbeda dari pekerja layanan yang saat ini diinstal—tetapi jangan mengubah URL pekerja layanan.
  • navigator.serviceWorker.register() dipanggil dengan URL yang sama seperti pekerja layanan yang diinstal, tetapi dengan cakupan yang berbeda. Sekali lagi, hindari ini dengan menjaga cakupan di root asal jika memungkinkan.
  • Saat peristiwa seperti 'push' atau 'sync' terpicu dalam 24 jam terakhir—tetapi jangan khawatir dengan peristiwa ini.

Cara pembaruan dilakukan

Mengetahui kapan browser mengupdate pekerja layanan sangatlah penting, begitu juga dengan "bagaimana". Dengan asumsi URL atau cakupan pekerja layanan tidak berubah, pekerja layanan yang saat ini diinstal hanya diupdate ke versi baru jika kontennya telah berubah.

Browser mendeteksi perubahan dengan beberapa cara:

  • Setiap perubahan byte per byte pada skrip yang diminta oleh importScripts, jika ada.
  • Setiap perubahan pada kode tingkat teratas pekerja layanan, yang memengaruhi sidik jari yang dihasilkan browser.

Browser melakukan banyak tugas berat di sini. Untuk memastikan browser memiliki semua yang diperlukan untuk mendeteksi perubahan pada konten pekerja layanan secara andal, jangan memberi tahu cache HTTP untuk menyimpannya, dan jangan mengubah nama filenya. Browser secara otomatis melakukan pemeriksaan pembaruan ketika ada navigasi ke halaman baru dalam cakupan pekerja layanan.

Memicu pemeriksaan update secara manual

Terkait pembaruan, logika pendaftaran umumnya tidak boleh berubah. Namun, satu pengecualian mungkin jika sesi di situs web berlangsung lama. Hal ini dapat terjadi dalam aplikasi web satu halaman ketika permintaan navigasi jarang terjadi, karena aplikasi biasanya menemukan satu permintaan navigasi di awal siklus proses aplikasi. Dalam situasi seperti ini, update manual dapat dipicu di thread utama:

navigator.serviceWorker.ready.then((registration) => {
  registration.update();
});

Untuk situs tradisional, atau dalam kasus apa pun dengan sesi pengguna tidak aktif dalam waktu lama, memicu update manual mungkin tidak diperlukan.

Penginstalan

Saat menggunakan bundler untuk membuat aset statis, aset tersebut akan berisi hash pada namanya, seperti framework.3defa9d2.js. Misalnya, beberapa aset tersebut di-pracache untuk akses offline nanti. Tindakan ini akan memerlukan update pekerja layanan untuk melakukan precache pada aset yang diperbarui:

self.addEventListener('install', (event) => {
  const cacheKey = 'MyFancyCacheName_v2';

  event.waitUntil(caches.open(cacheKey).then((cache) => {
    // Add all the assets in the array to the 'MyFancyCacheName_v2'
    // `Cache` instance for later use.
    return cache.addAll([
      '/css/global.ced4aef2.css',
      '/css/home.cbe409ad.css',
      '/js/home.109defa4.js',
      '/js/jquery.38caf32d.js'
    ]);
  }));
});

Dua hal berbeda dari contoh peristiwa install pertama dari contoh sebelumnya:

  1. Instance Cache baru dengan kunci 'MyFancyCacheName_v2' akan dibuat.
  2. Nama aset yang di-cache telah berubah.

Satu hal yang perlu diperhatikan adalah bahwa pekerja layanan yang diupdate akan diinstal bersama yang sebelumnya. Artinya, pekerja layanan lama masih mengontrol halaman yang terbuka, dan setelah penginstalan, pekerja layanan baru memasuki status menunggu hingga diaktifkan.

Secara default, pekerja layanan baru akan diaktifkan ketika tidak ada klien yang dikontrol oleh klien lama. Hal ini terjadi saat semua tab terbuka untuk situs yang relevan ditutup.

Aktivasi

Ketika pekerja layanan terbaru diinstal dan fase menunggu berakhir, pekerja layanan akan diaktifkan, dan pekerja layanan lama akan dihapus. Tugas umum yang harus dilakukan dalam peristiwa activate pekerja layanan yang diupdate adalah memangkas cache lama. Hapus cache lama dengan mendapatkan kunci untuk semua instance Cache yang terbuka dengan caches.keys dan menghapus cache yang tidak berada dalam daftar yang diizinkan yang ditentukan dengan caches.delete:

self.addEventListener('activate', (event) => {
  // Specify allowed cache keys
  const cacheAllowList = ['MyFancyCacheName_v2'];

  // Get all the currently active `Cache` instances.
  event.waitUntil(caches.keys().then((keys) => {
    // Delete all caches that aren't in the allow list:
    return Promise.all(keys.map((key) => {
      if (!cacheAllowList.includes(key)) {
        return caches.delete(key);
      }
    }));
  }));
});

Cache lama tidak rapi. Kami perlu melakukannya sendiri atau berisiko melebihi kuota penyimpanan. Karena 'MyFancyCacheName_v1' dari pekerja layanan pertama sudah tidak berlaku lagi, daftar yang diizinkan cache diperbarui untuk menentukan 'MyFancyCacheName_v2', yang menghapus cache dengan nama berbeda.

Peristiwa activate akan selesai setelah cache lama dihapus. Pada tahap ini, pekerja layanan baru akan mengambil alih halaman, yang akhirnya menggantikan pekerja layanan lama.

Siklus proses akan terus berlanjut

Baik Workbox digunakan untuk menangani deployment dan update pekerja layanan, atau jika API Pekerja Layanan digunakan secara langsung, pemahaman tentang siklus proses pekerja layanan akan bermanfaat. Dengan pemahaman itu, perilaku pekerja layanan harus tampak lebih logis daripada misterius.

Jika ingin mempelajari topik ini lebih dalam, sebaiknya baca artikel karya Jake Archibald. Ada banyak hal yang memengaruhi keseluruhan proses siklus proses layanan, tetapi hal ini dapat diketahui, dan pengetahuan tersebut akan bermanfaat saat menggunakan Workbox.