Pernahkah Anda mendengar lelucon bahwa jika Anda menginstal ServiceWorker, inilah saatnya untuk mengubah domain? Sekarang saya akan memberi tahu Anda apa artinya dan apa yang harus dilakukan jika Anda tetap memutuskan bahwa Anda memerlukan PWA.
Dalam petunjuk untuk jenis ini atau ini ServiceWorker dan bekerja dengan itu, hampir tidak ada perhatian dibayar. Dan saya yakin artikel seperti ini adalah hal pertama yang Anda baca sebelum menggunakannya. Tetapi pada saat, setelah artikel seperti itu, PWA Anda yang baru dipanggang akhirnya muncul di produksi dan pengguna memiliki kesempatan untuk menambahkan ikon lain ke desktop mereka, ketahuilah bahwa Anda telah melewati titik tanpa harapan.
Dengan izin Anda, saya tidak akan memikirkan uraian tentang Pekerja Layanan (selanjutnya disebut SW) dan cara kerjanya. Habré sudah memiliki artikel bagus tentang ini . Tidak peduli SW mana yang Anda miliki secara spesifik. Mungkin Anda menggunakan create-react-app , yang berarti pustaka Workbox bertanggung jawab atas SW . Mungkin Anda menerapkan SW sendiri, dengan beberapa strategi caching yang rumit. Tumpukan tidak terlalu penting. Dokumentasi CRA yang sama mengatakan bahwa yang Anda butuhkan hanyalah mengubah satu baris dan mendapatkan semua kesenangan dari perilaku seperti aplikasi. Anda telah menulis .register()
dan mengharapkan hasilnya. Dan Anda akan mendapatkannya.
Lain kali pelanggan yang tidak puas meminta Anda untuk mengubah warna tombol oranye ini atau akhirnya menyelesaikan bug fokus terbang itu, Anda akan menemukan diri Anda dalam situasi yang luar biasa. Ada perbaikan terbaru di repositori, wadah dirakit dan nginx mendistribusikan versi terbaru dengan pasti, tetapi untuk beberapa alasan klien masih tidak senang. Oh ya, kami sekarang menjadi PWA.
- Harap segarkan halaman. Bagaimana tidak membantu? Bagaimana jika CTRL + R?
Jadi, apa yang harus dilakukan ketika penyegaran halaman yang panik tidak membantu dan klien masih melihat tombol oranye yang mengejek?
Penting untuk diingat bahwa SW mencoba berperilaku seperti aplikasi desktop.
Mari kita ingat bagaimana aplikasi desktop memperbarui dirinya sendiri. Ini mengunduh penginstal baru, menghapus versi lama, dan menginstalnya kembali. Baru setelah itu pengguna menerima versi baru dari aplikasi tersebut.
SW.
SW : installing, waiting active. Active - , SW. installing waiting SW active. installing SW , . waiting , SW ( ). .
SW, , - . SW , . . , . , .
, , "". , SW : , , , . , SW . , .
SW installing, waiting active. - . , .
, , .
№1: SW
( ) - SW. SW skipWaiting()
, . SW . "" .
: , . , skipWaiting()
, , .
№2: SW
, . navigator.serviceWorker
controllerchange
, SW . installing.
skipWaiting()
, . :
navigator.serviceWorker.addEventListener('controllerchange', () => window.location.reload());
SW , .
, , . , , . .
№3:
, , SW , - - .
controllerchange
, , , .
, SW, ServiceWorkerRegistration
. .register()
, . API . , update()
, SW . , .
(active) SW navigator.serviceWorker.controller
active . (waiting) (installing) SW.
SW postMessage()
, iframe , API. SW . SW.
addEventListener('message', ev => {
if (ev.data === 'skipWaiting') return skipWaiting();
});
Selanjutnya, kita perlu melacak tampilan SW yang menunggu. Menurut saya, lebih baik tidak setiap kali bereaksi terhadap SW dengan status penginstalan, seperti yang tertulis di beberapa manual, tetapi menunggu hingga objek pendaftaran SW kembali benar di lapangan waiting
. Ini memperlambat pembaruan, tetapi tidak memicu modal Anda saat SW diinstal untuk pertama kalinya.
Setelah kami menunggu SW yang tertunda, kami memanggil jendela modal di mana pengguna dapat mengonfirmasi pembaruan. Setelah konfirmasi, kami memanggil skipWaiting()
dan memuat ulang halaman secara paksa seperti yang dijelaskan di atas. Jika terjadi kegagalan, pembaruan akan ditunda. Kode dalam kasus saya akan terlihat seperti ini:
//
const askUserToUpdate = reg => {
return Modal.confirm({
onOk: async () => {
//
navigator.serviceWorker.addEventListener('controllerchange', () => {
window.location.reload();
});
//
if (reg && reg.waiting) {
reg.waiting.postMessage({ type: 'SKIP_WAITING' });
}
},
onCancel: () => {
Modal.destroyAll();
},
icon: null,
title: ' !