Sulit untuk mengetahui apa yang dilakukan pekerja layanan tanpa memahami siklus prosesnya. Cara kerjanya akan tampak buram, bahkan arbitrer. Sebaiknya ingat bahwa—seperti API browser lainnya—perilaku pekerja layanan ditentukan dengan baik, ditentukan, dan memungkinkan aplikasi offline, sekaligus memfasilitasi update tanpa mengganggu pengalaman pengguna.
Sebelum mempelajari Workbox, penting untuk memahami siklus proses pekerja layanan agar tindakan Workbox masuk akal.
Menentukan istilah
Sebelum membahas siklus proses pekerja layanan, sebaiknya tentukan beberapa istilah terkait cara kerja siklus proses tersebut.
Kontrol dan cakupan
Ide kontrol sangat penting untuk memahami cara kerja pekerja layanan. Halaman yang dijelaskan sebagai dikontrol oleh pekerja layanan adalah halaman yang memungkinkan pekerja layanan untuk mencegat permintaan jaringan atas namanya. Pekerja layanan ada dan dapat melakukan pekerjaan 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 terletak di /subdir/sw.js
,
cakupan pekerja layanan adalah /subdir/
.
Untuk melihat cara kerja konsep cakupan, lihat contoh ini:
- Buka
https://service-worker-scope-viewer.glitch.me/subdir/index.html.
Pesan akan muncul yang menyatakan bahwa tidak ada pekerja layanan yang mengontrol halaman.
Namun, halaman tersebut mendaftarkan pekerja layanan dari
https://service-worker-scope-viewer.glitch.me/subdir/sw.js
. - Muat ulang halaman. Karena pekerja layanan telah terdaftar dan sekarang aktif, pekerja layanan tersebut mengontrol halaman. Formulir yang berisi cakupan pekerja layanan, status saat ini, dan URL-nya akan terlihat. Catatan: harus memuat ulang halaman tidak ada hubungannya dengan cakupan, tetapi siklus proses pekerja layanan, yang akan dijelaskan nanti.
- Sekarang, buka https://service-worker-scope-viewer.glitch.me/index.html. Meskipun pekerja layanan terdaftar di origin ini, masih ada pesan yang menyatakan bahwa saat ini tidak ada pekerja layanan. Hal ini karena halaman ini tidak berada dalam cakupan pekerja layanan terdaftar.
Cakupan membatasi halaman yang dikontrol oleh pekerja layanan.
Dalam contoh ini, artinya pekerja layanan yang dimuat dari /subdir/sw.js
hanya dapat mengontrol halaman yang terletak di /subdir/
atau sub-pohonnya.
Di atas adalah cara kerja cakupan secara default,
tetapi cakupan maksimum yang diizinkan dapat diganti dengan menetapkan
header respons Service-Worker-Allowed
,
serta meneruskan
opsi scope
ke metode register
.
Kecuali jika ada alasan yang sangat baik untuk membatasi cakupan pekerja layanan ke subset origin,
muat pekerja layanan dari direktori root server web sehingga cakupannya seluas mungkin,
dan jangan khawatir dengan header Service-Worker-Allowed
. Dengan begitu, semuanya akan jauh lebih mudah.
Klien
Saat dikatakan bahwa pekerja layanan mengontrol halaman, sebenarnya pekerja layanan mengontrol klien.
Klien adalah halaman terbuka yang URL-nya berada dalam cakupan pekerja layanan tersebut.
Secara khusus, ini adalah instance WindowClient
.
Siklus proses pekerja layanan baru
Agar pekerja layanan dapat mengontrol halaman, pekerja layanan harus dibuat terlebih dahulu. Mari kita mulai dengan apa yang terjadi saat pekerja layanan baru di-deploy untuk situs tanpa pekerja layanan 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:
- Karena kunjungan pertama pengguna ke situs terjadi tanpa pekerja layanan terdaftar, tunggu hingga halaman dimuat sepenuhnya sebelum mendaftarkannya. Hal ini menghindari pertentangan bandwidth jika pekerja layanan melakukan pra-cache apa pun.
- Meskipun pekerja layanan didukung dengan baik, pemeriksaan cepat membantu menghindari error di browser yang tidak mendukungnya.
- Saat 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 origin, karena dimuat dari direktori utama.
- Saat pendaftaran dimulai, status pekerja layanan ditetapkan ke
'installing'
.
Setelah pendaftaran selesai, penginstalan akan dimulai.
Penginstalan
Pekerja layanan memicu peristiwa
install
setelah pendaftaran.
install
hanya dipanggil sekali per pekerja layanan, dan tidak akan diaktifkan lagi hingga diperbarui.
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 pra-cache aset.
Kita akan memiliki banyak kesempatan untuk membahas pra-cache nanti,
jadi mari kita fokus pada peran
event.waitUntil
. event.waitUntil
menerima promise,
dan menunggu hingga promise tersebut di-resolve.
Dalam contoh ini, promise tersebut melakukan dua hal asinkron:
- Membuat instance
Cache
baru bernama'MyFancyCache_v1'
. - Setelah cache dibuat,
array URL aset dipra-cache menggunakan
metode
addAll
asinkronnya.
Penginstalan gagal jika promise yang diteruskan ke event.waitUntil
ditolak.
Jika hal ini terjadi, pekerja layanan akan dihapus.
Jika promise diselesaikan,
penginstalan akan 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,
tugas ini tidak relevan untuk saat ini,
dan akan diperluas saat kita membahas update pekerja layanan.
Untuk pekerja layanan baru, activate
akan langsung diaktifkan 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 atau pembaruan halaman berikutnya.
Menangani update pekerja layanan
Setelah pekerja layanan pertama di-deploy, pekerja layanan tersebut kemungkinan perlu diupdate nanti. Misalnya, update mungkin diperlukan jika terjadi perubahan pada logika pra-cache atau penanganan permintaan.
Kapan update terjadi
Browser akan memeriksa update pada 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 ubah URL pekerja layanan.navigator.serviceWorker.register()
dipanggil dengan URL yang sama dengan pekerja layanan yang diinstal, tetapi dengan cakupan yang berbeda. Sekali lagi, hindari hal ini dengan mempertahankan cakupan di root origin jika memungkinkan.- Jika peristiwa seperti
'push'
atau'sync'
telah dipicu dalam 24 jam terakhir—tetapi jangan khawatir dengan peristiwa ini.
Cara update dilakukan
Mengetahui kapan browser mengupdate pekerja layanan memang penting, tetapi "caranya" juga penting. Dengan asumsi URL atau cakupan service worker tidak berubah, service worker yang saat ini diinstal hanya akan diupdate ke versi baru jika kontennya telah berubah.
Browser mendeteksi perubahan dengan beberapa cara:
- Setiap perubahan byte demi byte pada skrip yang diminta oleh
importScripts
, jika ada. - Setiap perubahan pada kode tingkat atas pekerja layanan, yang memengaruhi sidik jari yang dihasilkan browser.
Browser melakukan banyak pekerjaan berat di sini. Untuk memastikan browser memiliki semua yang diperlukan untuk mendeteksi perubahan pada konten pekerja layanan dengan andal, jangan beri tahu cache HTTP untuk menyimpannya, dan jangan ubah nama filenya. Browser akan otomatis melakukan pemeriksaan update saat ada navigasi ke halaman baru dalam cakupan pekerja layanan.
Memicu pemeriksaan update secara manual
Terkait update, logika pendaftaran umumnya tidak boleh berubah. Namun, satu pengecualian mungkin terjadi jika sesi di situs memiliki masa aktif yang lama. Hal ini dapat terjadi di aplikasi web satu halaman tempat permintaan navigasi jarang terjadi, karena aplikasi biasanya mengalami satu permintaan navigasi di awal siklus proses aplikasi. Dalam situasi seperti itu, update manual dapat dipicu di thread utama:
navigator.serviceWorker.ready.then((registration) => {
registration.update();
});
Untuk situs tradisional, atau dalam kasus apa pun jika sesi pengguna tidak berlangsung lama, memicu update manual mungkin tidak diperlukan.
Penginstalan
Saat menggunakan bundler untuk membuat aset statis,
aset tersebut akan berisi hash dalam namanya,
seperti framework.3defa9d2.js
.
Misalkan beberapa aset tersebut dipra-cache untuk akses offline nanti.
Tindakan ini akan memerlukan update pekerja layanan untuk melakukan pra-cache 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'
]);
}));
});
Ada dua hal yang berbeda dari contoh peristiwa install
pertama sebelumnya:
- Instance
Cache
baru dengan kunci'MyFancyCacheName_v2'
akan dibuat. - Nama aset yang di-cache sebelumnya telah berubah.
Satu hal yang perlu diperhatikan adalah bahwa pekerja layanan yang diupdate akan diinstal bersama dengan pekerja layanan sebelumnya. Artinya, pekerja layanan lama masih mengontrol halaman yang terbuka, dan setelah penginstalan, pekerja layanan baru akan memasuki status menunggu hingga diaktifkan.
Secara default, pekerja layanan baru akan diaktifkan jika tidak ada klien yang dikontrol oleh pekerja layanan lama. Hal ini terjadi saat semua tab yang terbuka untuk situs yang relevan ditutup.
Aktivasi
Saat pekerja layanan yang diupdate diinstal dan fase tunggu berakhir, pekerja layanan tersebut akan diaktifkan, dan pekerja layanan lama akan dihapus.
Tugas umum yang harus dilakukan dalam peristiwa activate
pekerja layanan yang diperbarui adalah memangkas cache lama.
Hapus cache lama dengan mendapatkan kunci untuk semua instance Cache
yang terbuka dengan
caches.keys
dan menghapus cache yang tidak ada dalam daftar yang diizinkan 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 akan dibersihkan dengan sendirinya.
Kita harus melakukannya sendiri atau berisiko melebihi
kuota penyimpanan.
Karena 'MyFancyCacheName_v1'
dari pekerja layanan pertama sudah tidak berlaku,
daftar yang diizinkan cache diperbarui untuk menentukan 'MyFancyCacheName_v2'
,
yang menghapus cache dengan nama yang berbeda.
Peristiwa activate
akan selesai setelah cache lama dihapus.
Pada tahap ini, pekerja layanan baru akan mengambil alih kontrol halaman,
yang akhirnya menggantikan pekerja layanan lama.
Siklus proses terus berlanjut
Baik Workbox digunakan untuk menangani deployment dan update pekerja layanan, atau Service Worker API digunakan secara langsung, Anda sebaiknya memahami siklus proses pekerja layanan. Dengan pemahaman tersebut, perilaku pekerja layanan akan tampak lebih logis daripada misterius.
Bagi yang tertarik untuk mempelajari topik ini lebih dalam, baca artikel ini dari Jake Archibald. Ada banyak nuansa dalam cara kerja seluruh siklus proses layanan, tetapi dapat diketahui, dan pengetahuan tersebut akan sangat berguna saat menggunakan Workbox.