Pola pikir pekerja layanan

Bagaimana berpikir tentang pekerja layanan.

Pekerja layanan sangat hebat dan benar-benar layak untuk dipelajari. Iklan Display Responsif memungkinkan Anda memberikan tingkat pengalaman yang benar-benar baru kepada pengguna. Situs Anda dapat dimuat secara instan. Aplikasi ini dapat berfungsi secara offline. Google Play Protect dapat diinstal sebagai aplikasi khusus platform dan terasa setiap fiturnya sudah disempurnakan—tetapi dengan jangkauan dan kebebasan web.

Tapi pekerja layanan berbeda dari apa pun yang biasa digunakan oleh pengembang web. Mereka memiliki kurva belajar yang curam dan beberapa hambatan yang harus Anda waspadai.

Google Developers 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 memunculkan beberapa metafora yang menggambarkan. Dalam postingan ini, kita akan mengeksplorasi model mental ini dan memahami sifat paradoks yang membuat pekerja layanan rumit sekaligus mengagumkan.

Sama, tapi 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 promise seperti biasa.

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

Lapisan baru

Biasanya, saat membangun sebuah 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

Anggaplah 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 andal. 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. Muat ulang halaman sederhana tidak cukup untuk memperbarui pekerja layanan—sama seperti Anda tidak mengharapkan pemuatan ulang halaman untuk memperbarui kode yang di-deploy di server. Setiap lapisan memiliki aturan uniknya sendiri untuk pembaruan.

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

Canggih, tetapi terbatas

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

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

Dengan sebanyak mungkin pekerja layanan, mereka dibatasi oleh desain. Tidak dapat melakukan 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.

Berjangka panjang, tetapi berumur pendek

Pekerja layanan yang aktif akan terus aktif bahkan setelah pengguna meninggalkan situs atau menutup tab. Browser menjaga pekerja layanan ini tetap ada 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 berfungsi secara offline—pekerja layanan dapat menyajikan versi halaman yang di-cache, bahkan jika 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 pekerja layanan terkesan abadi, mereka dapat dihentikan kapan saja. Browser tidak ingin menyia-nyiakan resource pada pekerja layanan yang saat ini tidak melakukan apa pun. Berhenti 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 tidur, pekerja layanan Anda memerlukan cara untuk memberi tahu browser saat sedang melakukan sesuatu yang penting dan tidak terasa seperti tidur siang. Di sinilah event.waitUntil() berperan. Metode ini memperpanjang siklus proses yang digunakannya, mencegahnya dihentikan dan tidak berpindah ke fase berikutnya dari siklus hidupnya sampai kita siap. Ini memberi kita waktu untuk menyiapkan cache, mengambil resource dari jaringan, dll.

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

Hati-hati dengan kondisi global

Saat start/stop ini terjadi, cakupan global pekerja layanan akan direset. Jadi berhati-hatilah untuk tidak menggunakan status global apa pun pada pekerja layanan Anda. Jika tidak, Anda akan merasa sedih saat bangun 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 sebuah nomor—misalnya 0.13981866382421893. Variabel hasHandledARequest juga berubah menjadi true. Sekarang pekerja layanan tidak aktif sebentar, sehingga browser menghentikannya. Saat ada permintaan lagi, pekerja layanan akan diperlukan lagi, sehingga browser mengaktifkannya. 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 hal-hal seperti Saluran Pesan dapat menyebabkan bug: Anda akan mendapatkan instance baru setiap kali pekerja layanan berhenti/memulai.

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

visualisasi pekerja layanan yang dihentikan

Bersama-sama, tetapi terpisah

Halaman Anda hanya dapat dikontrol oleh satu pekerja layanan pada satu waktu. Namun, aplikasi ini 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. Service worker tidak dapat diubah. Anda membuat project yang baru. Pekerja layanan baru ini (sebut saja SW2) akan diinstal tetapi belum diaktifkan. Sistem harus menunggu hingga pekerja layanan saat ini (SW1) dihentikan (saat pengguna keluar dari situs).

Mengotak-atik cache pekerja layanan lain

Saat menginstal, SW2 bisa melakukan pengaturan—biasanya membuat dan mengisi {i>cache<i}. 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 menyebabkan masalah Anda:

  • SW2 dapat menghapus {i>cache<i} yang digunakan secara aktif SW1.
  • SW2 dapat mengedit isi cache yang digunakan SW1, menyebabkan SW1 merespons dengan aset yang tidak diharapkan halaman.

Lewati skipMenunggu

Pekerja layanan juga dapat menggunakan metode skipWaiting() yang berisiko untuk mengontrol halaman segera setelah penginstalan selesai. Ini adalah ide yang buruk kecuali Anda sengaja mencoba mengganti pekerja layanan yang memiliki bug. Pekerja layanan baru mungkin menggunakan resource terbaru 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 {i>cache<i} 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 menambahkan version agar melakukan apa yang diperlukan 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 redundan. Pada titik ini, penting untuk melakukan pembersihan setelah pekerja layanan lama. Tidak hanya menghormati penyimpanan cache, tetapi juga mencegah {i>bug <i}yang tidak disengaja.

Metode caches.match() adalah pintasan yang sering digunakan untuk mengambil item dari cache apa pun yang memiliki kecocokan. Namun, perintah ini mengiterasi 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 merusak situs Anda.

Yang diperlukan untuk melakukan pembersihan setelah pekerja layanan sebelumnya adalah menghapus cache apa pun yang tidak diperlukan 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 melakukan clobbing satu sama lain membutuhkan kerja keras dan disiplin, tetapi hal ini 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 memahami mereka, Anda akan dapat menciptakan pengalaman yang luar biasa bagi pengguna Anda.

Jika ingin memahami semua ini dengan memainkan game, Anda beruntung! Buka Service Workies tempat Anda akan mempelajari cara pekerja layanan untuk membasmi monster offline.