Hal yang dipelajari tim Bulletin tentang pekerja layanan saat mengembangkan PWA.
Ini adalah seri entri blog pertama tentang pelajaran yang diperoleh tim Google Bulletin saat membuat PWA yang ditampilkan ke eksternal. Dalam postingan ini, kami akan membagikan beberapa tantangan yang kami hadapi, pendekatan yang kami lakukan untuk mengatasinya, dan saran umum untuk menghindari masalah. Ini bukan ringkasan lengkap tentang PWA. Tujuannya adalah untuk berbagi pembelajaran dari pengalaman tim kami.
Untuk postingan pertama ini, kita akan membahas sedikit informasi latar belakang terlebih dahulu, lalu mempelajari semua hal yang telah kita pelajari tentang pekerja layanan.
Latar belakang
Buletin sedang dalam pengembangan aktif dari pertengahan 2017 hingga pertengahan 2019.
Alasan kami memilih untuk membuat PWA
Sebelum mempelajari proses pengembangan, mari kita pelajari mengapa mem-build PWA adalah opsi yang menarik untuk project ini:
- Kemampuan untuk melakukan iterasi dengan cepat. Sangat berharga karena Bulletin akan diuji coba di beberapa pasar.
- Code base tunggal. Pengguna kami terbagi secara merata antara Android dan iOS. PWA berarti kita dapat mem-build satu aplikasi web yang akan berfungsi di kedua platform. Hal ini meningkatkan kecepatan dan dampak tim.
- Diperbarui dengan cepat dan terpisah dari perilaku pengguna. PWA dapat otomatis diupdate sehingga mengurangi jumlah klien yang sudah tidak berlaku di dunia nyata. Kami dapat mendorong perubahan backend yang melanggar dengan waktu migrasi yang sangat singkat untuk klien.
- Mudah diintegrasikan dengan aplikasi pihak pertama dan pihak ketiga. Integrasi tersebut merupakan persyaratan untuk aplikasi. Dengan PWA, sering kali berarti hanya membuka URL.
- Menghilangkan hambatan penginstalan aplikasi.
Framework kami
Untuk Buletin, kami menggunakan Polymer, tetapi framework modern yang didukung dengan baik akan berfungsi.
Yang kita pelajari tentang pekerja layanan
Anda tidak dapat memiliki PWA tanpa pekerja layanan. Pekerja layanan memberi Anda banyak kemampuan, seperti strategi penyimpanan dalam cache lanjutan, kemampuan offline, sinkronisasi latar belakang, dll. Meskipun pekerja layanan memang menambahkan beberapa kompleksitas, kami mendapati bahwa manfaatnya lebih besar daripada kompleksitas tambahan.
Buat jika Anda bisa
Hindari menulis skrip pekerja layanan secara manual. Menulis pekerja layanan secara manual memerlukan pengelolaan resource yang di-cache secara manual dan penulisan ulang logika yang umum untuk sebagian besar library pekerja layanan, seperti Workbox.
Oleh karena itu, karena tech stack internal, kami tidak dapat menggunakan library untuk menghasilkan dan mengelola pekerja layanan kita. Pembelajaran kami di bawah ini terkadang akan mencerminkan hal tersebut. Buka Kekurangan pekerja layanan yang tidak dibuat untuk membaca selengkapnya.
Tidak semua library kompatibel dengan pekerja layanan
Beberapa library JS membuat asumsi yang tidak berfungsi seperti yang diharapkan saat dijalankan oleh pekerja layanan. Misalnya, dengan asumsi window
atau document
tersedia, atau penggunaan API tidak tersedia untuk pekerja layanan (XMLHttpRequest
, penyimpanan lokal, dll.). Pastikan library penting apa pun yang diperlukan untuk aplikasi Anda kompatibel dengan pekerja layanan. Untuk PWA khusus ini, kami ingin menggunakan gapi.js untuk autentikasi, tetapi tidak dapat melakukannya karena tidak mendukung pekerja layanan. Penulis library juga harus mengurangi atau menghapus
asumsi yang tidak perlu tentang konteks JavaScript jika memungkinkan untuk mendukung kasus penggunaan
service worker, seperti dengan menghindari API yang tidak kompatibel dengan service worker dan menghindari status
global.
Menghindari akses IndexedDB selama inisialisasi
Jangan membaca IndexedDB saat melakukan inisialisasi skrip pekerja layanan, atau Anda dapat mengalami situasi yang tidak diinginkan ini:
- Pengguna memiliki aplikasi web dengan IndexedDB (IDB) versi N
- Aplikasi web baru didorong dengan IDB versi N+1
- Pengguna mengunjungi PWA, yang memicu download pekerja layanan baru
- Pekerja layanan baru membaca dari IDB sebelum mendaftarkan pengendali peristiwa
install
, sehingga memicu siklus upgrade IDB untuk beralih dari N ke N+1 - Karena pengguna memiliki klien lama dengan versi N, proses upgrade pekerja layanan akan berhenti berfungsi karena koneksi aktif masih terbuka untuk database versi lama
- Pekerja layanan hang, dan tidak pernah menginstal
Dalam kasus kita, cache menjadi tidak valid pada penginstalan pekerja layanan, sehingga jika pekerja layanan tidak pernah diinstal, pengguna tidak akan pernah menerima aplikasi yang telah diupdate.
Membuatnya tangguh
Meskipun skrip pekerja layanan berjalan di latar belakang, skrip tersebut juga dapat dihentikan kapan saja, bahkan saat berada di tengah operasi I/O (jaringan, IDB, dll.). Setiap proses yang berjalan lama harus dapat dilanjutkan kapan saja.
Dalam kasus proses sinkronisasi yang mengupload file besar ke server dan disimpan ke IDB, solusi kami untuk upload parsial yang terganggu adalah memanfaatkan sistem yang dapat dilanjutkan library upload internal kami, menyimpan URL upload yang dapat dilanjutkan ke IDB sebelum mengupload, dan menggunakan URL tersebut untuk melanjutkan upload jika tidak selesai pada pertama kalinya. Selain itu, sebelum operasi I/O yang berjalan lama, status disimpan ke IDB untuk menunjukkan posisi kita dalam proses untuk setiap kumpulan data.
Jangan bergantung pada status global
Karena pekerja layanan ada dalam konteks yang berbeda, banyak simbol yang mungkin Anda harapkan tidak ada. Banyak kode kami yang berjalan dalam konteks window
, serta konteks pekerja layanan (seperti logging, flag, sinkronisasi, dll.). Kode harus bersifat defensif terhadap layanan yang digunakannya, seperti
penyimpanan lokal atau cookie. Anda dapat menggunakan
globalThis
untuk merujuk ke objek global dengan cara yang akan berfungsi di semua konteks. Selain itu, gunakan data yang disimpan
dalam variabel global seperlunya, karena tidak ada jaminan kapan skrip akan dihentikan dan
status dihapus.
Pengembangan lokal
Komponen utama pekerja layanan adalah menyimpan resource secara lokal dalam cache. Namun, selama pengembangan, hal ini
adalah kebalikan yang Anda inginkan, terutama jika update dilakukan dengan lambat. Anda tetap ingin
petugas server diinstal agar dapat men-debug masalah terkait atau menggunakan API lain seperti
sinkronisasi latar belakang, atau notifikasi. Di Chrome, Anda dapat melakukannya melalui Chrome DevTools dengan mengaktifkan kotak centang Bypass for network (panel Application > panel Service workers) selain mengaktifkan kotak centang Disable cache di panel Network untuk juga menonaktifkan cache memori. Untuk mencakup lebih banyak browser, kami memilih solusi lain dengan menyertakan tanda untuk menonaktifkan penyimpanan cache di pekerja layanan kami yang diaktifkan secara default pada build developer. Hal ini memastikan bahwa developer selalu mendapatkan perubahan terbaru tanpa masalah penyimpanan dalam cache. Anda juga harus menyertakan header Cache-Control: no-cache
untuk mencegah browser menyimpan aset dalam cache.
Mercusuar
Lighthouse menyediakan sejumlah alat proses debug yang berguna untuk PWA. Alat ini memindai situs dan membuat laporan yang mencakup PWA, performa, aksesibilitas, SEO, dan praktik terbaik lainnya. Sebaiknya jalankan Lighthouse pada integrasi berkelanjutan untuk memberi tahu Anda jika Anda melanggar salah satu kriteria untuk menjadi PWA. Hal ini sebenarnya pernah terjadi pada kami, saat pekerja layanan tidak diinstal dan kami tidak menyadarinya sebelum push produksi. Jika Lighthouse menjadi bagian dari CI, hal itu akan mencegahnya.
Menerapkan continuous delivery
Karena pekerja layanan dapat otomatis diupdate, pengguna tidak dapat membatasi upgrade. Hal ini secara signifikan mengurangi jumlah klien yang sudah tidak berlaku di dunia nyata. Saat pengguna membuka aplikasi kita, pekerja layanan akan melayani klien lama selagi mendownload klien baru dengan lambat. Setelah didownload, klien baru akan meminta pengguna untuk memuat ulang halaman guna mengakses fitur baru. Meskipun pengguna mengabaikan permintaan ini, saat berikutnya mereka memuat ulang halaman, mereka akan menerima klien versi baru. Akibatnya, cukup sulit bagi pengguna untuk menolak update dengan cara yang sama seperti yang dapat mereka lakukan untuk aplikasi iOS/Android.
Kami dapat menerapkan perubahan backend yang menyebabkan error dengan waktu migrasi yang sangat singkat untuk klien. Biasanya, kami akan memberikan waktu satu bulan bagi pengguna untuk melakukan update ke klien yang lebih baru sebelum melakukan perubahan yang dapat menyebabkan gangguan. Karena aplikasi akan ditayangkan saat sudah tidak berlaku, klien lama sebenarnya dapat ada di luar sana jika pengguna sudah lama tidak membuka aplikasi. Di iOS, pekerja layanan dihapus setelah beberapa minggu sehingga kasus ini tidak terjadi. Untuk Android, masalah ini dapat dimitigasi dengan tidak menayangkan konten saat sudah tidak berlaku, atau mengakhiri konten secara manual setelah beberapa minggu. Dalam praktiknya, kami tidak pernah mengalami masalah dari klien yang sudah tidak berlaku. Tingkat kepatuhan tim tertentu di sini bergantung pada kasus penggunaan tertentu, tetapi PWA memberikan fleksibilitas yang jauh lebih besar daripada aplikasi iOS/Android.
Mendapatkan nilai cookie di pekerja layanan
Terkadang perlu untuk mengakses nilai cookie dalam konteks pekerja layanan. Dalam kasus ini, kita
perlu mengakses nilai cookie untuk membuat token guna mengautentikasi permintaan API pihak pertama. Dalam
pekerja layanan, API sinkron seperti document.cookies
tidak tersedia. Anda selalu dapat mengirim
pesan ke klien aktif (berjendela) dari pekerja layanan untuk meminta nilai cookie, meskipun pekerja layanan dapat berjalan di latar belakang tanpa klien berjenis jendela
tersedia, seperti selama sinkronisasi latar belakang. Untuk mengatasi hal ini, kita membuat endpoint di
server frontend yang meneruskan nilai cookie kembali ke klien. Pekerja layanan membuat
permintaan jaringan ke endpoint ini dan membaca respons untuk mendapatkan nilai cookie.
Dengan dirilisnya Cookie Store API, solusi ini seharusnya tidak diperlukan lagi oleh browser yang mendukungnya, karena solusi ini menyediakan akses asinkron ke cookie browser dan dapat digunakan langsung oleh pekerja layanan.
Perangkap untuk pekerja layanan non-hasil
Memastikan skrip pekerja layanan berubah jika ada perubahan file yang di-cache statis
Pola PWA yang umum adalah untuk pekerja layanan menginstal semua file aplikasi statis selama
fase install
, yang memungkinkan klien mengakses cache Cache Storage API secara langsung untuk semua
kunjungan berikutnya. Service worker hanya diinstal saat browser mendeteksi bahwa skrip
service worker telah berubah dengan cara tertentu, sehingga kita harus memastikan file skrip service worker itu sendiri
berubah dengan cara tertentu saat file yang di-cache berubah. Kami melakukannya secara manual dengan menyematkan hash
fileset resource statis dalam skrip pekerja layanan, sehingga setiap rilis menghasilkan
file JavaScript pekerja layanan yang berbeda. Library pekerja layanan seperti
Workbox mengotomatiskan proses ini untuk Anda.
Pengujian unit
API pekerja layanan berfungsi dengan menambahkan pemroses peristiwa ke objek global. Contoh:
self.addEventListener('fetch', (evt) => evt.respondWith(fetch('/foo')));
Hal ini dapat menjadi masalah untuk diuji karena Anda perlu membuat tiruan pemicu peristiwa, objek peristiwa, menunggu
callback respondWith()
, lalu menunggu promise, sebelum akhirnya menyatakan hasil. Cara
yang lebih mudah untuk menyusunnya adalah dengan mendelegasikan semua implementasi ke file lain, yang lebih mudah
diuji.
import fetchHandler from './fetch_handler.js';
self.addEventListener('fetch', (evt) => evt.respondWith(fetchHandler(evt)));
Karena kesulitan pengujian unit pada skrip pekerja layanan, kami mempertahankan skrip pekerja layanan inti sesederhana mungkin, dengan membagi sebagian besar implementasi ke dalam modul lain. Karena file-file tersebut hanyalah modul JS standar, file tersebut dapat lebih mudah diuji unit dengan library pengujian standar.
Nantikan bagian 2 dan 3
Di bagian 2 dan 3 seri ini, kami akan membahas tentang pengelolaan media dan masalah khusus iOS. Jika Anda ingin bertanya lebih lanjut tentang cara membuat PWA di Google, kunjungi profil penulis kami untuk mengetahui cara menghubungi kami: