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 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 bermanfaat karena Buletin akan diuji coba di beberapa pasar.
- Basis kode 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 tidak bergantung pada perilaku pengguna. PWA dapat otomatis diupdate sehingga mengurangi jumlah klien yang sudah tidak berlaku di dunia nyata. Kami dapat menerapkan perubahan backend yang dapat menyebabkan gangguan 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, hal ini 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 telah 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 menggunakan API yang tidak tersedia untuk pekerja
layanan (XMLHttpRequest
, penyimpanan lokal, dll.). Pastikan library penting yang Anda perlukan untuk
aplikasi 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 menginisialisasi skrip pekerja layanan, atau Anda akan masuk ke dalam situasi yang tidak diinginkan ini:
- Pengguna memiliki aplikasi web dengan IndexedDB (IDB) versi N
- Aplikasi web baru diluncurkan 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
, yang 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 macet, dan tidak pernah diinstal
Dalam kasus kami, cache tidak valid saat menginstal pekerja layanan, sehingga jika pekerja layanan tidak pernah diinstal, pengguna tidak akan pernah menerima aplikasi yang diupdate.
Buat 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 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 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 dari yang Anda inginkan, terutama saat update dilakukan secara lambat. Anda tetap ingin
pekerja server diinstal agar dapat men-debug masalah terkaitnya 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 yang berbeda dengan
menyertakan tanda untuk menonaktifkan penyimpanan dalam cache di pekerja layanan kami yang diaktifkan secara default pada build
developer. Hal ini memastikan bahwa developer selalu mendapatkan perubahan terbaru tanpa masalah caching. 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.
Mendukung 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 memuat ulang halaman lagi, mereka akan menerima versi baru klien. 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 mengupdate ke klien yang lebih baru sebelum membuat perubahan yang 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 dikeluarkan setelah beberapa minggu sehingga hal ini tidak terjadi. Untuk Android, masalah ini dapat dimitigasi dengan tidak menayangkan saat sudah tidak berlaku, atau dengan menetapkan masa berlaku 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, Anda perlu mengakses nilai cookie dalam konteks pekerja layanan. Dalam kasus ini, kita perlu mengakses nilai cookie untuk membuat token guna mengautentikasi permintaan API pihak pertama. Di 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 hanya mencerminkan nilai cookie kembali ke klien. Pekerja layanan membuat
permintaan jaringan ke endpoint ini dan membaca respons untuk mendapatkan nilai cookie.
Dengan rilis Cookie Store API, solusi ini tidak lagi diperlukan untuk browser yang mendukungnya, karena menyediakan akses asinkron ke cookie browser dan dapat digunakan langsung oleh pekerja layanan.
Perangkap untuk pekerja layanan yang tidak dibuat
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. Pekerja layanan hanya diinstal saat browser mendeteksi bahwa skrip pekerja layanan telah berubah dengan cara tertentu. Jadi, kita harus memastikan file skrip pekerja layanan 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 serial ini, kita akan membahas pengelolaan media dan masalah khusus iOS. Jika Anda ingin bertanya lebih lanjut tentang cara membuat PWA di Google, buka profil penulis kami untuk mengetahui cara menghubungi kami: