Cara berpikir saat memikirkan pekerja layanan.
Service worker sangat canggih dan benar-benar layak dipelajari. Fitur ini memungkinkan Anda memberikan tingkat pengalaman yang sama sekali baru kepada pengguna. Situs Anda dapat dimuat secara instan. Aplikasi ini dapat berfungsi secara offline. Aplikasi ini dapat diinstal sebagai aplikasi khusus platform dan terasa sama canggihnya—tetapi dengan jangkauan dan kebebasan web.
Namun, pekerja layanan tidak seperti yang biasa digunakan oleh sebagian besar developer web. Mereka memiliki kurva belajar yang curam dan beberapa hambatan yang harus Anda waspadai.
Developer Google dan saya baru-baru ini berkolaborasi dalam sebuah project—Service Workies—game gratis untuk memahami pekerja layanan. Saat membangun dan bekerja dengan seluk-beluk pekerja layanan yang kompleks, saya mengalami beberapa masalah. Hal yang paling membantu saya adalah membuat beberapa metafora deskriptif. Dalam postingan ini, kita akan mengeksplorasi model mental ini dan memahami sifat-sifat paradoks yang membuat pekerja layanan rumit sekaligus mengagumkan.
Sama, tetapi berbeda
Saat membuat kode pekerja layanan, banyak hal yang akan terasa familier. Anda dapat menggunakan fitur bahasa JavaScript baru favorit Anda. Anda memproses peristiwa siklus proses seperti halnya peristiwa UI. Anda mengelola alur kontrol dengan promise seperti biasa.
Namun, perilaku pekerja layanan lainnya membuat Anda bingung. Terutama saat Anda memuat ulang halaman dan tidak melihat perubahan kode diterapkan.
Lapisan baru
Biasanya, saat mem-build situs, Anda hanya perlu memikirkan dua lapisan: klien dan server. Service worker adalah lapisan baru yang berada di tengah.
Anggap pekerja layanan Anda sebagai semacam ekstensi browser—yang dapat diinstal situs Anda di browser pengguna. Setelah diinstal, pekerja layanan akan memperluas browser untuk situs Anda dengan lapisan tengah yang canggih. Lapisan pekerja layanan ini dapat mencegat dan menangani semua permintaan yang dibuat situs Anda.
Lapisan pekerja layanan memiliki siklus prosesnya sendiri yang tidak bergantung pada tab browser. Memuat ulang halaman sederhana tidak cukup untuk mengupdate pekerja layanan—sama seperti Anda tidak mengharapkan pemuatan ulang halaman untuk mengupdate kode yang di-deploy di server. Setiap lapisan memiliki aturan unik untuk pembaruan.
Dalam game Service Workies, kami membahas banyak detail siklus proses pekerja layanan dan memberi Anda banyak latihan untuk menggunakannya.
Efektif, tetapi terbatas
Memiliki pekerja layanan di situs akan memberi Anda manfaat luar biasa. Situs Anda dapat:
- berfungsi dengan baik meskipun pengguna sedang offline
- mendapatkan peningkatan performa yang signifikan melalui cache
- menggunakan notifikasi push
- dapat diinstal sebagai PWA
Dengan sebanyak mungkin pekerja layanan, mereka dibatasi oleh desain. Mereka tidak dapat melakukan apa pun secara sinkron atau dalam thread yang sama dengan situs Anda. Artinya, tidak ada akses ke:
- localStorage
- DOM
- jendela
Kabar baiknya adalah ada beberapa cara yang dapat digunakan halaman Anda untuk berkomunikasi dengan pekerja layanannya, termasuk postMessage
langsung, Saluran Pesan one-to-one, dan Saluran Siaran one-to-many.
Berumur panjang, tetapi berumur pendek
Pekerja layanan yang aktif akan terus aktif bahkan setelah pengguna meninggalkan situs atau menutup tab. Browser menyimpan pekerja layanan ini agar siap saat pengguna kembali ke situs Anda. Sebelum permintaan pertama dibuat, pekerja layanan mendapatkan kesempatan untuk mencegatnya dan mengontrol halaman. Hal inilah yang memungkinkan situs berfungsi secara offline—service worker dapat menayangkan versi halaman yang di-cache itu sendiri, meskipun pengguna tidak memiliki koneksi ke internet.
Di Service Workies, kami memvisualisasikan konsep ini bersama Kolohe (pekerja layanan yang ramah) yang mencegat dan menangani permintaan.
Dihentikan
Meskipun tampak abadi, pekerja layanan dapat dihentikan hampir setiap saat. Browser tidak ingin menyia-nyiakan resource pada pekerja layanan yang saat ini tidak melakukan apa pun. Dihentikan tidak sama dengan dihentikan—pekerja layanan tetap diinstal dan diaktifkan. Alat ini hanya disetel untuk tidur. Saat diperlukan lagi (misalnya, untuk menangani permintaan), browser akan mengaktifkannya kembali.
waitUntil
Karena kemungkinan terus-menerus dinonaktifkan, pekerja layanan Anda memerlukan cara untuk memberi tahu browser saat melakukan sesuatu yang penting dan tidak ingin tidur siang. Di sinilah event.waitUntil()
berperan. Metode ini memperluas siklus proses tempatnya digunakan, sehingga tidak berhenti dan tidak beralih ke fase berikutnya dalam siklus prosesnya hingga kita siap. Ini memberi kita waktu untuk menyiapkan cache, mengambil resource dari jaringan, dll.
Contoh ini memberi tahu browser bahwa penginstalan pekerja layanan belum selesai hingga cache assets
dibuat dan diisi dengan gambar pedang:
self.addEventListener("install", event => {
event.waitUntil(
caches.open("assets").then(cache => {
return cache.addAll(["/weapons/sword/blade.png"]);
})
);
});
Memperhatikan status global
Saat start/stop ini terjadi, cakupan global pekerja layanan akan direset. Jadi, berhati-hatilah untuk tidak menggunakan status global apa pun di pekerja layanan Anda atau Anda akan kecewa saat pekerja layanan diaktifkan kembali dan memiliki status yang berbeda dari yang diharapkan.
Perhatikan contoh berikut yang menggunakan status global:
const favoriteNumber = Math.random();
let hasHandledARequest = false;
self.addEventListener("fetch", event => {
console.log(favoriteNumber);
console.log(hasHandledARequest);
hasHandledARequest = true;
});
Pada setiap permintaan, pekerja layanan ini akan mencatat nomor—misalnya 0.13981866382421893
. Variabel hasHandledARequest
juga berubah menjadi true
. Sekarang pekerja layanan tidak ada aktivitas sejenak, sehingga browser menghentikannya. Saat berikutnya ada permintaan, pekerja layanan diperlukan lagi, sehingga browser akan membangunkannya. Skripnya dievaluasi lagi. Sekarang hasHandledARequest
direset ke false
, dan favoriteNumber
adalah sesuatu yang benar-benar berbeda—0.5907281835659033
.
Anda tidak dapat mengandalkan status tersimpan di pekerja layanan. Selain itu, membuat instance seperti Message Channel dapat menyebabkan bug: Anda akan mendapatkan instance baru setiap kali pekerja layanan berhenti/dimulai.
Di Service Worker bab 3, kita memvisualisasikan pekerja layanan yang dihentikan sebagai kehilangan semua warna saat menunggu untuk diaktifkan.
Bersama, tetapi terpisah
Halaman Anda hanya dapat dikontrol oleh satu pekerja layanan dalam satu waktu. Namun, aplikasi dapat memiliki dua pekerja layanan yang diinstal sekaligus. Saat Anda membuat perubahan pada kode pekerja layanan dan memuat ulang halaman, Anda sebenarnya tidak mengedit pekerja layanan sama sekali. Pekerja layanan tidak dapat diubah. Sebagai gantinya, Anda membuat akun baru. Pekerja layanan baru ini (sebut saja SW2) akan diinstal, tetapi belum akan diaktifkan. Service worker baru harus menunggu hingga service worker saat ini (SW1) dihentikan (saat pengguna meninggalkan situs Anda).
Mengganggu cache pekerja layanan lain
Saat menginstal, SW2 dapat menyiapkan semuanya—biasanya membuat dan mengisi cache. Namun, perhatikan: pekerja layanan baru ini memiliki akses ke semua hal yang dapat diakses oleh pekerja layanan saat ini. Jika Anda tidak berhati-hati, pekerja layanan yang baru menunggu dapat benar-benar mengacaukan pekerja layanan Anda saat ini. Beberapa contoh yang dapat menyebabkan masalah:
- SW2 dapat menghapus cache yang aktif digunakan SW1.
- SW2 dapat mengedit konten cache yang digunakan SW1, sehingga menyebabkan SW1 merespons dengan aset yang tidak diharapkan halaman.
Lewati skipWaiting
Pekerja layanan juga dapat menggunakan metode skipWaiting()
yang berisiko untuk mengambil kendali halaman segera setelah selesai diinstal. Ini umumnya bukan ide yang buruk kecuali Anda sengaja mencoba mengganti pekerja layanan yang memiliki bug. Service worker baru mungkin menggunakan resource yang diperbarui yang tidak diharapkan halaman saat ini, sehingga menyebabkan error dan bug.
Mulai pembersihan
Cara untuk mencegah service worker Anda meng-clone satu sama lain adalah dengan memastikan mereka menggunakan cache yang berbeda. Cara termudah untuk melakukannya adalah dengan membuat versi nama cache yang digunakan.
const version = 1;
const assetCacheName = `assets-${version}`;
self.addEventListener("install", event => {
caches.open(assetCacheName).then(cache => {
// confidently do stuff with your very own cache
});
});
Saat men-deploy pekerja layanan baru, Anda akan mengganti version
sehingga dapat melakukan hal yang diperlukan dengan cache yang sepenuhnya terpisah dari pekerja layanan sebelumnya.
Akhiri pembersihan
Setelah pekerja layanan mencapai status activated
, Anda tahu bahwa pekerja layanan tersebut telah mengambil alih, dan pekerja layanan sebelumnya menjadi redundan. Pada tahap ini, Anda harus membersihkan service worker lama. Hal ini tidak hanya mematuhi batas penyimpanan cache pengguna, tetapi juga dapat mencegah bug yang tidak disengaja.
Metode caches.match()
adalah pintasan yang sering digunakan untuk mengambil item dari cache apa pun yang memiliki kecocokan. Namun, cache akan di-iterasi sesuai urutan pembuatannya. Misalkan Anda memiliki dua versi file skrip app.js
dalam dua cache yang berbeda—assets-1
dan assets-2
. Halaman Anda mengharapkan skrip yang lebih baru yang disimpan di assets-2
. Namun, jika Anda belum menghapus cache lama, caches.match('app.js')
akan menampilkan cache lama dari assets-1
dan kemungkinan besar akan merusak situs Anda.
Yang diperlukan untuk membersihkan setelah pekerja layanan sebelumnya adalah menghapus cache yang tidak diperlukan oleh pekerja layanan baru:
const version = 2;
const assetCacheName = `assets-${version}`;
self.addEventListener("activate", event => {
event.waitUntil(
caches.keys().then(cacheNames => {
return Promise.all(
cacheNames.map(cacheName => {
if (cacheName !== assetCacheName){
return caches.delete(cacheName);
}
});
);
});
);
});
Mencegah pekerja layanan Anda saling bertabrakan memerlukan sedikit kerja keras dan disiplin, tetapi hasilnya sepadan.
Pola pikir pekerja layanan
Memahami pola pikir yang tepat saat memikirkan pekerja layanan akan membantu Anda membangunnya dengan percaya diri. Setelah memahaminya, Anda akan dapat menciptakan pengalaman yang luar biasa bagi pengguna.
Jika Anda ingin memahami semua ini dengan memainkan game, Anda beruntung. Mainkan Service Workies tempat Anda akan mempelajari cara kerja service worker untuk mengalahkan monster offline.