Membuat PWA di Google, bagian 1

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

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

Ini adalah rangkaian postingan blog pertama tentang pelajaran yang dipelajari tim Google Buletin saat membangun PWA untuk eksternal. Dalam postingan ini, kami akan membagikan beberapa tantangan yang kami hadapi, pendekatan yang kami ambil untuk mengatasinya, dan saran umum untuk menghindari jebakan. Ini sama sekali bukan merupakan 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 dan kemudian membahas semua hal yang telah kita pelajari tentang pekerja layanan.

Latar belakang

Buletin dikembangkan secara aktif dari pertengahan tahun 2017 hingga pertengahan tahun 2019.

Alasan kami memilih untuk membuat PWA

Sebelum mempelajari proses pengembangan, mari kita cari tahu mengapa membangun PWA adalah pilihan yang menarik untuk project ini:

  • Kemampuan untuk melakukan iterasi dengan cepat. Hal ini sangat berharga karena Buletin akan diuji coba di beberapa pasar.
  • Basis kode tunggal. Pengguna kami kira-kira terbagi secara merata antara Android dan iOS. PWA berarti kita dapat membuat satu aplikasi web yang akan berfungsi di kedua platform. Hal ini meningkatkan kecepatan dan dampak tim.
  • Diperbarui dengan cepat dan independen dari perilaku pengguna. PWA dapat diupdate secara otomatis, sehingga mengurangi jumlah klien usang. Kami dapat menerapkan perubahan backend yang dapat menyebabkan gangguan dengan waktu migrasi klien yang sangat singkat.
  • Mudah diintegrasikan dengan aplikasi pihak pertama dan ketiga. Integrasi tersebut merupakan persyaratan untuk aplikasi. Dengan PWA, sering kali hanya perlu membuka URL.
  • Menghilangkan hambatan saat menginstal aplikasi.

Framework kami

Untuk Buletin, kami menggunakan Polymer, tetapi framework modern yang didukung dengan baik akan berfungsi.

Apa yang telah kita pelajari tentang pekerja layanan

Anda tidak dapat memiliki PWA tanpa pekerja layanan. Pekerja layanan memberi Anda banyak kemampuan, seperti strategi caching lanjutan, kemampuan offline, sinkronisasi latar belakang, dll. Meskipun pekerja layanan memiliki beberapa kerumitan, 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 dan penulisan ulang logika yang umum bagi sebagian besar library pekerja layanan, seperti Workbox.

Meskipun demikian, karena tech stack internal, kami tidak dapat menggunakan library untuk membuat dan mengelola pekerja layanan. Pembelajaran dari kami di bawah ini terkadang akan mencerminkan hal tersebut. Buka Masalah untuk pekerja layanan yang tidak dihasilkan 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 apa pun yang Anda perlukan untuk aplikasi kompatibel dengan pekerja layanan. Khusus untuk PWA 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 diperlukan tentang konteks JavaScript jika memungkinkan untuk mendukung kasus penggunaan pekerja layanan, seperti dengan menghindari API yang tidak kompatibel dengan pekerja layanan dan menghindari status global.

Hindari mengakses IndexedDB selama inisialisasi

Jangan baca 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 diluncurkan 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 dari N ke N+1
  5. Karena pengguna memiliki klien lama dengan versi N, proses upgrade pekerja layanan macet karena koneksi aktif masih terbuka ke database versi lama
  6. Pekerja layanan hang, dan tidak pernah menginstal

Dalam kasus kita, cache dibatalkan saat penginstalan pekerja layanan dilakukan, sehingga jika pekerja layanan tidak pernah diinstal, pengguna tidak akan pernah menerima aplikasi yang diupdate.

Buat konten yang tangguh

Meskipun skrip pekerja layanan berjalan di latar belakang, skrip tersebut juga dapat dihentikan kapan saja, bahkan saat sedang menjalankan 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 sebagian yang terganggu adalah memanfaatkan sistem library upload internal yang dapat dilanjutkan, menyimpan URL upload yang dapat dilanjutkan ke IDB sebelum mengupload, dan menggunakan URL tersebut untuk melanjutkan upload jika upload tidak selesai untuk pertama kalinya. Juga, sebelum operasi I/O yang berjalan lama, status disimpan ke IDB untuk menunjukkan posisi kita untuk setiap kumpulan data dalam proses.

Jangan bergantung pada status global

Karena pekerja layanan ada dalam konteks yang berbeda, banyak simbol yang mungkin Anda harapkan tidak ada. Banyak kode kita yang dijalankan dalam konteks window, serta konteks pekerja layanan (seperti logging, flag, sinkronisasi, dll.). Kode harus bersifat defensif terkait 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 dikeluarkan.

Pengembangan lokal

Komponen utama pekerja layanan meng-cache resource secara lokal. Namun, selama pengembangan, hal ini merupakan kebalikan yang Anda inginkan, terutama saat update dilakukan dengan lambat. Anda tetap ingin pekerja server diinstal agar dapat men-debug masalah dengannya atau menggunakan API lain, seperti sinkronisasi latar belakang, atau notifikasi. Di Chrome, Anda dapat melakukannya melalui Chrome DevTools dengan mengaktifkan kotak centang Abaikan untuk jaringan (panel Application > Service worker) selain mengaktifkan kotak centang Disable cache di panel Network untuk menonaktifkan cache memori juga. Untuk mencakup lebih banyak browser, kami memilih solusi yang berbeda 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 caching. Header Cache-Control: no-cache juga harus disertakan untuk mencegah browser menyimpan aset apa pun dalam cache.

Mercusuar

Lighthouse menyediakan sejumlah alat proses debug yang berguna untuk PWA. Google Play Protect memindai situs dan menghasilkan laporan yang mencakup PWA, performa, aksesibilitas, SEO, dan praktik terbaik lainnya. Sebaiknya jalankan Lighthouse pada integrasi berkelanjutan untuk memberi tahu jika Anda melanggar salah satu kriteria untuk menjadi PWA. Ini pernah terjadi pada kami, saat pekerja layanan tidak menginstal dan kami tidak menyadarinya sebelum push produksi. Dengan memiliki Lighthouse sebagai bagian dari CI kami, hal itu akan dapat mencegah hal tersebut.

Menerapkan continuous delivery

Karena pekerja layanan dapat mengupdate secara otomatis, pengguna tidak memiliki kemampuan untuk membatasi upgrade. Hal ini secara signifikan mengurangi jumlah klien yang sudah usang. Saat pengguna membuka aplikasi, pekerja layanan akan melayani klien lama sementara mendownload klien baru dengan lambat. Setelah klien baru didownload, pengguna akan diminta memuat ulang halaman agar dapat mengakses fitur baru. Meskipun pengguna mengabaikan permintaan ini, saat berikutnya mereka memuat ulang halaman, mereka akan menerima versi baru klien. Akibatnya, cukup sulit bagi pengguna untuk menolak update dengan cara yang sama seperti yang mereka lakukan untuk aplikasi iOS/Android.

Kami dapat menerapkan perubahan backend yang dapat menyebabkan gangguan 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 tidak digunakan, klien lama mungkin akan tetap eksis jika pengguna tidak membuka aplikasi untuk waktu yang lama. Di iOS, pekerja layanan akan dikeluarkan setelah beberapa minggu sehingga kasus ini tidak terjadi. Untuk Android, masalah ini dapat dimitigasi dengan tidak menayangkan konten saat sudah tidak berlaku, atau menghentikan masa berlaku konten secara manual setelah beberapa minggu. Pada praktiknya, kami tidak pernah mengalami masalah dari klien yang sudah tidak relevan. Seberapa ketat tim tertentu ingin berada di sini bergantung pada kasus penggunaan mereka yang spesifik, tetapi PWA memberikan fleksibilitas yang jauh lebih besar daripada aplikasi iOS/Android.

Mendapatkan nilai cookie dalam pekerja layanan

Terkadang, Anda perlu mengakses nilai cookie dalam konteks pekerja layanan. Dalam kasus ini, kita perlu mengakses nilai cookie guna membuat token untuk mengautentikasi permintaan API pihak pertama. Dalam pekerja layanan, API sinkron seperti document.cookies tidak tersedia. Anda selalu dapat mengirim pesan ke klien yang aktif (berjendela) dari pekerja layanan untuk meminta nilai cookie, meskipun pekerja layanan dapat berjalan di latar belakang tanpa klien berjendela yang tersedia, seperti saat sinkronisasi latar belakang. Untuk mengatasi hal ini, kami 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 dirilisnya 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.

Kesalahan untuk pekerja layanan yang tidak dihasilkan

Pastikan skrip pekerja layanan berubah jika ada perubahan file yang di-cache statis

Pola PWA yang umum ditujukan bagi pekerja layanan untuk menginstal semua file aplikasi statis selama fase install, yang memungkinkan klien membuka cache Cache Storage API secara langsung untuk semua kunjungan berikutnya . Pekerja layanan hanya akan diinstal jika browser mendeteksi bahwa skrip pekerja layanan telah berubah dengan cara tertentu. Jadi, kami harus memastikan file skrip pekerja layanan itu sendiri berubah sedemikian rupa ketika 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 mungkin sulit untuk diuji karena Anda perlu meniru pemicu peristiwa, objek peristiwa, menunggu callback respondWith(), lalu menunggu promise, sebelum akhirnya menegaskan pada hasilnya. Cara yang lebih mudah untuk menyusun struktur ini 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 dalam menguji unit skrip pekerja layanan, kami menyimpan skrip pekerja layanan inti sesederhana mungkin, dengan membagi sebagian besar implementasi ke dalam modul lain. Karena file tersebut hanya merupakan 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 pengelolaan media dan masalah khusus iOS. Jika Anda ingin bertanya lebih lanjut kepada kami tentang cara membuat PWA di Google, kunjungi profil penulis kami untuk mengetahui cara menghubungi kami: