Membuat PWA di Google, bagian 1

Hal yang dipelajari tim Bulletin tentang pekerja layanan saat mengembangkan PWA.

Douglas Parker
Douglas Parker
Joel Riley
Joel Riley
Dikla Cohen
Dikla Cohen

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

Bulletin sedang dalam pengembangan aktif dari pertengahan 2017 hingga pertengahan 2019.

Alasan kami memilih untuk membuat PWA

Sebelum mempelajari proses pengembangan, mari kita pelajari mengapa membuat 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 tidak bergantung pada perilaku pengguna. PWA dapat otomatis diupdate sehingga mengurangi jumlah klien yang sudah tidak berlaku di dunia nyata. Kami dapat mendorong perubahan backend yang mendobrak 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 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.

Meskipun demikian, karena stack teknologi internal kami, kami tidak dapat menggunakan library untuk membuat dan mengelola pekerja layanan. 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 melakukan inisialisasi skrip pekerja layanan, atau Anda dapat mengalami situasi yang tidak diinginkan ini:

  1. Pengguna memiliki aplikasi web dengan IndexedDB (IDB) versi N
  2. Aplikasi web baru didorong dengan IDB versi N+1
  3. Pengguna mengunjungi PWA, yang memicu download pekerja layanan baru
  4. Pekerja layanan baru membaca dari IDB sebelum mendaftarkan pengendali peristiwa install, yang memicu siklus upgrade IDB untuk beralih dari N ke N+1
  5. Karena pengguna memiliki klien lama dengan versi N, proses upgrade pekerja layanan akan berhenti berfungsi karena koneksi aktif masih terbuka untuk database versi lama
  6. 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 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 dari yang Anda inginkan, terutama saat update dilakukan secara 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 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 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, service worker akan menayangkan klien lama sambil mendownload klien baru secara lambat. Setelah klien baru didownload, klien 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 klien yang 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 gangguan dengan waktu migrasi yang sangat singkat untuk klien. Biasanya, kami akan memberi pengguna waktu satu bulan 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 dihapus setelah beberapa minggu sehingga kasus 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 perubahan skrip pekerja layanan jika ada perubahan file statis yang di-cache

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 set file 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 tersebut hanyalah modul JS standar, file tersebut dapat diuji unit dengan lebih mudah menggunakan 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: