Pekerja layanan yang lebih baru, secara default

tl;dr

Mulai Chrome 68, permintaan HTTP yang memeriksa update pada skrip pekerja layanan tidak akan lagi dipenuhi oleh cache HTTP secara default. Tindakan ini mengatasi titik masalah developer yang umum, saat menetapkan header Cache-Control yang tidak disengaja pada skrip pekerja layanan dapat menyebabkan update tertunda.

Jika sudah menonaktifkan penyimpanan cache HTTP untuk skrip /service-worker.js dengan menayangkannya bersama Cache-Control: max-age=0, Anda tidak akan melihat perubahan apa pun karena perilaku default baru.

Selain itu, mulai Chrome 78, perbandingan byte-untuk-byte akan diterapkan ke skrip yang dimuat di pekerja layanan melalui importScripts(). Setiap perubahan yang dibuat pada skrip yang diimpor akan memicu alur update pekerja layanan, sama seperti perubahan pada pekerja layanan tingkat teratas.

Latar belakang

Setiap kali Anda membuka halaman baru yang berada dalam cakupan pekerja layanan, panggil registration.update() secara eksplisit dari JavaScript, atau saat pekerja layanan "dibangunkan" melalui peristiwa push atau sync, secara paralel browser akan meminta resource JavaScript yang awalnya diteruskan ke panggilan navigator.serviceWorker.register(), untuk mencari pembaruan pada skrip pekerja layanan.

Untuk tujuan artikel ini, anggap saja URL-nya adalah /service-worker.js dan berisi satu panggilan ke importScripts(), yang memuat kode tambahan yang dijalankan di dalam pekerja layanan:

// Inside our /service-worker.js file:
importScripts('path/to/import.js');

// Other top-level code goes here.

Apa yang berubah?

Sebelum Chrome 68, permintaan update untuk /service-worker.js akan dibuat melalui cache HTTP (seperti kebanyakan pengambilan). Artinya, jika skrip awalnya dikirim dengan Cache-Control: max-age=600, update dalam 600 detik berikutnya (10 menit) tidak akan sampai ke jaringan, sehingga pengguna mungkin tidak menerima versi terbaru pekerja layanan. Namun, jika max-age lebih besar dari 86400 (24 jam), nilainya akan diperlakukan seolah-olah adalah 86400, untuk mencegah pengguna terjebak dengan versi tertentu selamanya.

Mulai versi 68, cache HTTP akan diabaikan saat meminta update untuk skrip pekerja layanan, sehingga aplikasi web yang ada mungkin mengalami peningkatan frekuensi permintaan untuk skrip pekerja layanannya. Permintaan untuk importScripts akan tetap melalui cache HTTP. Namun, ini hanyalah opsi default—tersedia opsi pendaftaran baru updateViaCache yang menawarkan kontrol atas perilaku ini.

updateViaCache

Developer kini dapat meneruskan opsi baru saat memanggil navigator.serviceWorker.register(): parameter updateViaCache. Fungsi ini menggunakan salah satu dari tiga nilai: 'imports', 'all', atau 'none'.

Nilai ini menentukan apakah dan bagaimana cache HTTP standar browser berperan saat membuat permintaan HTTP untuk memeriksa resource pekerja layanan terbaru.

  • Jika ditetapkan ke 'imports', cache HTTP tidak akan dimintai masukannya saat memeriksa update pada skrip /service-worker.js, tetapi akan diminta bantuan saat mengambil skrip yang diimpor (dalam contoh kita adalah path/to/import.js). Ini adalah setelan default, dan cocok dengan perilaku yang dimulai di Chrome 68.

  • Jika ditetapkan ke 'all', cache HTTP akan diperiksa saat membuat permintaan untuk skrip /service-worker.js tingkat teratas, serta skrip apa pun yang diimpor di dalam pekerja layanan, seperti path/to/import.js. Opsi ini sesuai dengan perilaku sebelumnya di Chrome, sebelum Chrome 68.

  • Jika ditetapkan ke 'none', cache HTTP tidak akan diperhatikan saat membuat permintaan untuk /service-worker.js tingkat teratas atau untuk skrip yang diimpor, seperti hipotesis path/to/import.js.

Misalnya, kode berikut akan mendaftarkan pekerja layanan, dan memastikan bahwa cache HTTP tidak pernah diperiksa saat memeriksa update pada skrip /service-worker.js, atau untuk skrip apa pun yang direferensikan melalui importScripts() di dalam /service-worker.js:

if ('serviceWorker' in navigator) {
  navigator.serviceWorker.register('/service-worker.js', {
    updateViaCache: 'none',
    // Optionally, set 'scope' here, if needed.
  });
}

Pemeriksaan update pada skrip yang diimpor

Sebelum Chrome 78, semua skrip pekerja layanan yang dimuat melalui importScripts() hanya akan diambil satu kali (memeriksa cache HTTP terlebih dahulu, atau melalui jaringan, bergantung pada konfigurasi updateViaCache). Setelah diambil awal tersebut, data akan disimpan secara internal oleh browser, dan tidak pernah diambil kembali.

Satu-satunya cara untuk memaksa pekerja layanan yang sudah diinstal agar mengambil perubahan pada skrip yang diimpor adalah dengan mengubah URL skrip, biasanya dengan menambahkan nilai semver (misalnya importScripts('https://example.com/v1.1.0/index.js')) atau dengan menyertakan hash konten (misalnya, importScripts('https://example.com/index.abcd1234.js')). Efek samping dari mengubah URL yang diimpor adalah perubahan konten skrip pekerja layanan tingkat atas.

Mulai Chrome 78, setiap kali pemeriksaan update dilakukan untuk file pekerja layanan tingkat teratas, pemeriksaan akan dilakukan secara bersamaan untuk menentukan apakah konten skrip yang diimpor telah berubah atau tidak. Bergantung pada header Cache-Control yang digunakan, pemeriksaan skrip yang diimpor ini mungkin dipenuhi oleh cache HTTP jika updateViaCache ditetapkan ke 'all' atau 'imports' (yang merupakan nilai default), atau pemeriksaan mungkin langsung ke jaringan jika updateViaCache ditetapkan ke 'none'.

Jika pemeriksaan update untuk skrip yang diimpor menghasilkan perbedaan byte-untuk-byte dibandingkan dengan apa yang sebelumnya disimpan oleh pekerja layanan, hal tersebut pada gilirannya akan memicu alur update pekerja layanan penuh, meskipun jika file pekerja layanan tingkat teratas tetap sama.

Perilaku Chrome 78 sesuai dengan yang diterapkan Firefox beberapa tahun lalu, di Firefox 56. Safari juga sudah menerapkan perilaku ini.

Apa yang harus dilakukan developer?

Jika Anda secara efektif menonaktifkan penyimpanan cache HTTP untuk skrip /service-worker.js dengan menayangkannya menggunakan Cache-Control: max-age=0 (atau nilai serupa), Anda tidak akan melihat perubahan apa pun karena perilaku default baru.

Jika Anda menayangkan skrip /service-worker.js dengan cache HTTP diaktifkan, baik secara sengaja maupun karena itu hanya setelan default untuk lingkungan hosting Anda, Anda mungkin akan mulai melihat peningkatan permintaan HTTP tambahan untuk /service-worker.js yang dibuat terhadap server Anda. Permintaan ini adalah permintaan yang biasanya dipenuhi oleh cache HTTP. Jika ingin terus mengizinkan nilai header Cache-Control memengaruhi keaktualan /service-worker.js, Anda harus mulai menyetel updateViaCache: 'all' secara eksplisit saat mendaftarkan pekerja layanan.

Mengingat mungkin ada longtail pengguna di versi browser lama, sebaiknya terus setel header HTTP Cache-Control: max-age=0 pada skrip pekerja layanan, meskipun browser yang lebih baru mungkin mengabaikannya.

Developer dapat menggunakan kesempatan ini untuk memutuskan apakah mereka ingin secara eksplisit mengecualikan skrip yang diimpor dari cache HTTP sekarang, dan menambahkan updateViaCache: 'none' ke pendaftaran pekerja layanan jika sesuai.

Menyajikan skrip yang diimpor

Mulai Chrome 78, developer mungkin melihat lebih banyak permintaan HTTP yang masuk untuk resource yang dimuat melalui importScripts(), karena developer kini akan diperiksa untuk update.

Jika Anda ingin menghindari traffic HTTP tambahan ini, tetapkan header Cache-Control yang berumur panjang saat menayangkan skrip yang menyertakan semver atau hash di URL-nya, dan andalkan perilaku updateViaCache default 'imports'.

Atau, jika Anda ingin skrip yang diimpor diperiksa untuk sering update, pastikan Anda menayangkannya dengan Cache-Control: max-age=0, atau menggunakan updateViaCache: 'none'.

Bacaan lebih lanjut

"The Service Worker Lifecycle" dan "Caching best practice & max-age gotchas", keduanya oleh Jake Archibald, direkomendasikan sebagai bacaan bagi semua developer yang men-deploy apa pun ke web.