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. Hal ini mengatasi titik masalah umum developer, yang menetapkan header Cache-Control yang tidak disengaja pada skrip pekerja layanan dapat menyebabkan update tertunda.

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

Selain itu, mulai Chrome 78, perbandingan byte demi byte akan diterapkan ke skrip yang dimuat di pekerja layanan melalui importScripts(). Setiap perubahan yang dilakukan 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 "diaktifkan" melalui peristiwa push atau sync, browser akan secara paralel meminta resource JavaScript yang awalnya diteruskan ke panggilan navigator.serviceWorker.register(), untuk mencari update pada skrip pekerja layanan.

Untuk tujuan artikel ini, asumsikan 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 dilakukan melalui cache HTTP (seperti sebagian besar pengambilan). Artinya, jika skrip awalnya dikirim dengan Cache-Control: max-age=600, update dalam 600 detik (10 menit) berikutnya tidak akan dikirim ke jaringan, sehingga pengguna mungkin tidak menerima versi terbaru pekerja layanan. Namun, jika max-age lebih besar dari 86400 (24 jam), max-age akan diperlakukan seolah-olah 86400, agar pengguna tidak terjebak dengan versi tertentu selamanya.

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

updateViaCache

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

Nilai ini menentukan apakah dan bagaimana cache HTTP standar browser digunakan saat membuat permintaan HTTP untuk memeriksa resource pekerja layanan yang diperbarui.

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

  • Jika ditetapkan ke 'all', cache HTTP akan dikonsultasikan saat membuat permintaan untuk skrip /service-worker.js level 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 dikonsultasikan saat membuat permintaan untuk /service-worker.js tingkat atas atau untuk skrip yang diimpor, seperti path/to/import.js hipotetik.

Misalnya, kode berikut akan mendaftarkan pekerja layanan, dan memastikan bahwa cache HTTP tidak pernah dikonsultasikan 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.
  });
}

Memeriksa update pada skrip yang diimpor

Sebelum Chrome 78, skrip pekerja layanan apa pun yang dimuat melalui importScripts() hanya akan diambil satu kali (pertama-tama memeriksa cache HTTP, atau melalui jaringan, bergantung pada konfigurasi updateViaCache). Setelah pengambilan awal, data tersebut akan disimpan secara internal oleh browser, dan tidak akan diambil lagi.

Satu-satunya cara untuk memaksa pekerja layanan yang telah diinstal untuk 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 konten skrip pekerja layanan tingkat atas berubah, yang pada akhirnya memicu alur update pekerja layanan.

Mulai Chrome 78, setiap kali pemeriksaan update dilakukan untuk file pekerja layanan level 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 dapat dipenuhi oleh cache HTTP jika updateViaCache ditetapkan ke 'all' atau 'imports' (yang merupakan nilai default), atau pemeriksaan dapat langsung dilakukan terhadap jaringan jika updateViaCache ditetapkan ke 'none'.

Jika pemeriksaan update untuk skrip yang diimpor menghasilkan perbedaan byte-per-byte dibandingkan dengan yang sebelumnya disimpan oleh pekerja layanan, hal ini pada gilirannya akan memicu alur update pekerja layanan lengkap, meskipun file pekerja layanan tingkat atas tetap sama.

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

Apa yang harus dilakukan developer?

Jika Anda telah memilih untuk tidak menggunakan cache HTTP untuk skrip /service-worker.js secara efektif dengan menayangkannya dengan 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 mengaktifkan cache HTTP, baik secara sengaja maupun karena itu adalah default untuk lingkungan hosting Anda, Anda mungkin mulai melihat peningkatan permintaan HTTP tambahan untuk /service-worker.js yang dibuat terhadap server Anda—ini adalah permintaan yang sebelumnya dipenuhi oleh cache HTTP. Jika ingin terus mengizinkan nilai header Cache-Control memengaruhi keaktualan /service-worker.js, Anda harus mulai menetapkan updateViaCache: 'all' secara eksplisit saat mendaftarkan pekerja layanan.

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

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

Menayangkan skrip yang diimpor

Mulai Chrome 78, developer mungkin melihat lebih banyak permintaan HTTP masuk untuk resource yang dimuat melalui importScripts(), karena resource tersebut 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 mengandalkan perilaku updateViaCache default dari 'imports'.

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

Bacaan lebih lanjut

"Siklus Proses Pekerja Layanan" dan "Praktik terbaik penyimpanan dalam cache & masalah max-age", keduanya oleh Jake Archibald, adalah bacaan yang direkomendasikan untuk semua developer yang men-deploy apa pun ke web.