Pola pikir pekerja layanan

Bagaimana memikirkan tentang pekerja layanan.

Service worker sangat hebat dan benar-benar layak untuk dipelajari. Keduanya memungkinkan Anda memberikan tingkat pengalaman yang benar-benar baru kepada pengguna. Situs Anda dapat dimuat langsung. Fitur ini dapat berfungsi offline. Software ini dapat diinstal sebagai aplikasi khusus platform dan terasa lebih rapi—tetapi dengan jangkauan dan kebebasan web.

Namun, pekerja layanan tidak seperti apa pun yang umumnya digunakan oleh developer web. Mereka memiliki kurva belajar yang curam dan beberapa hambatan yang harus Anda waspadai.

Google Developers dan saya baru-baru ini berkolaborasi dalam sebuah proyek—Service Workies—sebuah 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 memunculkan beberapa metafora gambaran. Dalam postingan ini, kita akan mempelajari model mental ini dan memfokuskan pikiran kita pada sifat paradoks yang membuat pekerja layanan itu rumit sekaligus mengagumkan.

Sama, tetapi berbeda

Saat melakukan coding pekerja layanan, banyak hal 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 janji seperti yang biasa Anda lakukan.

Tetapi perilaku pekerja layanan lainnya menyebabkan Anda menggaruk-garuk kepala karena kebingungan. Terutama saat Anda memuat ulang halaman dan tidak melihat perubahan kode Anda diterapkan.

Lapisan baru

Biasanya saat membangun situs, Anda hanya perlu memikirkan dua lapisan: klien dan server. Pekerja layanan adalah lapisan baru yang berada di tengah.

Pekerja layanan bertindak sebagai lapisan tengah antara klien dan server

Bayangkan pekerja layanan Anda sebagai semacam ekstensi browser—ekstensi yang dapat diinstal oleh situs Anda di browser pengguna. Setelah diinstal, pekerja layanan extends 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 terpisah dari tab browser. Muat ulang halaman sederhana tidak cukup untuk memperbarui pekerja layanan—sama seperti Anda tidak mengharapkan pemuatan ulang halaman untuk memperbarui kode yang di-deploy pada server. Setiap lapisan memiliki aturan uniknya sendiri untuk memperbarui.

Dalam game Service Workies, kami membahas berbagai detail siklus proses pekerja layanan dan memberi Anda banyak latihan untuk menggunakannya.

Andal, tetapi terbatas

Memiliki pekerja layanan di situs Anda memberikan manfaat yang luar biasa. Situs Anda dapat:

  • bekerja dengan sempurna bahkan ketika pengguna sedang {i>offline<i}
  • mendapatkan peningkatan performa besar-besaran melalui cache
  • gunakan notifikasi push
  • diinstal sebagai PWA

Dengan sebanyak yang dapat dilakukan pekerja layanan, mereka dibatasi oleh desain. Properti gabungan tidak dapat melakukan tindakan apa pun secara sinkron atau di 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.

Berusia panjang, tetapi berumur pendek

Pekerja layanan yang aktif akan tetap hidup bahkan setelah pengguna meninggalkan situs atau menutup tab. Browser terus menyimpan pekerja layanan ini sehingga akan siap saat pengguna kembali ke situs Anda. Sebelum permintaan pertama dibuat, pekerja layanan mendapat kesempatan untuk mencegatnya dan mengambil alih halaman. Inilah yang memungkinkan situs bekerja secara offline—pekerja layanan dapat menampilkan versi halaman yang di-cache, bahkan jika pengguna tidak memiliki koneksi ke internet.

Di Service Workies, kami memvisualisasikan konsep ini dengan Kolohe (pekerja layanan yang ramah) yang menangkap dan menangani permintaan.

Dihentikan

Meskipun pekerja layanan tampak abadi, mereka dapat dihentikan hampir setiap saat. Browser tidak ingin menyia-nyiakan resource pada pekerja layanan yang saat ini tidak melakukan apa pun. Menghentikan penggunaan tidak sama dengan dihentikan—service worker tetap terinstal dan diaktifkan. Perangkat ini akan tidur. Saat diperlukan lagi (mis., untuk menangani permintaan), browser akan membangunkannya kembali.

waitUntil

Karena kemungkinan untuk tidur secara terus-menerus, pekerja layanan Anda memerlukan cara untuk memberi tahu browser ketika melakukan sesuatu yang penting dan tidak terasa seperti tidur siang. Di sinilah event.waitUntil() berperan. Metode ini memperpanjang siklus proses yang digunakannya, sehingga mencegahnya dihentikan dan beralih ke fase berikutnya dalam siklus prosesnya hingga kita siap. Ini memberi kita waktu untuk menyiapkan cache, mengambil sumber daya dari jaringan, dll.

Contoh ini memberi tahu browser bahwa pekerja layanan tidak selesai diinstal 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"]);
    })
  );
});

Waspadai kondisi global

Jika aktivitas mulai/berhenti ini terjadi, cakupan global pekerja layanan akan direset. Jadi, berhati-hatilah untuk tidak menggunakan status global di pekerja layanan, atau Anda akan sedih saat pekerja itu bangun kembali dan memiliki kondisi yang berbeda dari yang diharapkan.

Perhatikan contoh yang menggunakan status global ini:

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 angka—misalnya 0.13981866382421893. Variabel hasHandledARequest juga berubah menjadi true. Sekarang pekerja layanan tidak ada aktivitas selama beberapa saat, sehingga browser akan menghentikannya. Saat ada permintaan berikutnya, pekerja layanan akan 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 yang disimpan dalam pekerja layanan. Selain itu, membuat instance hal-hal seperti Message Channels dapat menyebabkan bug: Anda akan mendapatkan instance baru setiap kali pekerja layanan berhenti/dimulai.

Dalam Service Workies bab 3, kita memvisualisasikan pekerja layanan yang dihentikan sehingga kehilangan semua warna saat menunggu untuk diaktifkan.

visualisasi pekerja layanan yang dihentikan

Bersama-sama, tetapi terpisah

Halaman Anda hanya dapat dikontrol oleh satu pekerja layanan dalam satu waktu. Namun, aplikasi ini dapat memiliki dua pekerja layanan yang diinstal sekaligus. Jika Anda membuat perubahan pada kode pekerja layanan dan memuat ulang halaman, Anda sebenarnya tidak mengedit pekerja layanan sama sekali. Pekerja layanan tidak dapat diubah. Anda membuat yang baru. Pekerja layanan baru ini (sebut saja SW2) akan menginstal, tetapi belum diaktifkan. Aplikasi harus menunggu pekerja layanan (SW1) saat ini berhenti bekerja (saat pengguna meninggalkan situs).

Mengotak-atik cache pekerja layanan lain

Saat menginstal, SW2 dapat melakukan pengaturan berbagai hal—biasanya membuat dan mengisi cache. Namun, perhatikan: pekerja layanan baru ini memiliki akses ke semua 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 menimbulkan masalah bagi Anda:

  • SW2 dapat menghapus cache yang secara aktif digunakan SW1.
  • SW2 dapat mengedit konten cache yang digunakan SW1, menyebabkan SW1 merespons dengan aset yang tidak diharapkan halaman.

Lewati lewatiMenunggu

Pekerja layanan juga dapat menggunakan metode skipWaiting() yang berisiko untuk mengontrol halaman segera setelah selesai diinstal. Ini umumnya bukan ide yang bagus kecuali jika Anda sengaja mencoba mengganti pekerja layanan yang berisi bug. Pekerja layanan baru mungkin menggunakan resource yang diupdate yang tidak diharapkan oleh halaman saat ini, sehingga menyebabkan error dan bug.

Mulai bersihkan

Cara untuk mencegah pekerja layanan Anda menyusupi satu sama lain adalah dengan memastikan bahwa mereka menggunakan cache yang berbeda. Cara termudah untuk melakukannya adalah dengan membuat versi nama cache yang mereka gunakan.

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 menempelkan version agar melakukan apa yang diperlukannya dengan cache yang sepenuhnya terpisah dari pekerja layanan sebelumnya.

visualisasi cache

Akhiri pembersihan

Setelah pekerja layanan mencapai status activated, Anda tahu bahwa pekerja layanan telah mengambil alih, dan pekerja layanan sebelumnya menjadi redundan. Pada tahap ini, penting untuk melakukan pembersihan setelah pekerja layanan lama. Tidak hanya menghormati batas penyimpanan cache pengguna, tetapi juga mencegah bug yang tidak disengaja.

Metode caches.match() adalah pintasan yang sering digunakan untuk mengambil item dari cache mana pun yang cocok. Namun, sistem akan melakukan iterasi melalui cache 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 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 melakukan pembersihan 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 membajak satu sama lain membutuhkan sedikit usaha dan disiplin tapi sepadan dengan manfaatnya.

Pola pikir pekerja layanan

Memiliki pola pikir yang benar saat memikirkan pekerja layanan akan membantu Anda membangun pola pikir Anda dengan percaya diri. Setelah Anda menguasainya, Anda akan dapat menciptakan pengalaman yang luar biasa bagi pengguna Anda.

Jika ingin memahami semua ini dengan memainkan game, maka Anda beruntung! Buka Service Workies. Di sini, Anda akan mempelajari cara-cara pekerja layanan untuk membunuh monster offline.