Membuat PWA di Google, bagian 1

Yang telah dipelajari tim Buletin tentang pekerja layanan saat mengembangkan PWA.

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

Ini adalah postingan pertama dari rangkaian postingan blog tentang pelajaran yang dipelajari tim Buletin Google saat membangun PWA yang berinteraksi secara eksternal. Dalam postingan ini, kami akan membagikan beberapa tantangan yang kami hadapi, pendekatan yang kami ambil untuk mengatasinya, dan saran umum untuk menghindari perangkap. Ini tidak berarti ringkasan PWA yang lengkap. Tujuannya adalah berbagi pembelajaran dari pengalaman tim kami.

Untuk postingan pertama ini, kami akan membahas sedikit informasi latar belakang terlebih dahulu dan kemudian membahas semua hal-hal yang 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 kita menyelami proses pengembangan, mari kita lihat mengapa membangun PWA menjadi menarik untuk project ini:

  • Kemampuan untuk melakukan iterasi dengan cepat. Sangat bermanfaat karena Buletin akan diuji coba dalam di berbagai pasar.
  • Basis kode tunggal. Pengguna kami terbelah secara merata antara Android dan iOS. PWA berarti kita bisa membuat satu aplikasi web yang akan berfungsi di kedua platform. Hal ini meningkatkan kecepatan dan dampak dari tim.
  • Diperbarui dengan cepat dan terpisah dari perilaku pengguna. PWA dapat otomatis memperbarui mengurangi jumlah klien yang sudah usang. Kami dapat mengirim backend yang bermasalah perubahan dengan waktu migrasi yang sangat singkat untuk klien.
  • Terintegrasi dengan mudah dengan aplikasi pihak pertama dan ketiga. Integrasi tersebut adalah persyaratan untuk aplikasi. Dengan PWA, sering kali berarti hanya membuka URL.
  • Hilangnya hambatan penginstalan aplikasi.

Kerangka kerja kami

Untuk Buletin, kami menggunakan Polymer, tetapi aplikasi Buletin modern akan berfungsi.

Yang telah kita pelajari tentang pekerja layanan

Anda tidak dapat memiliki PWA tanpa layanan pekerja. Service worker memberi Anda banyak kemampuan, seperti strategi {i>caching<i} lanjutan, kemampuan {i>offline<i}, sinkronisasi latar belakang, dll. Walaupun pekerja layanan menambah kerumitan, kami menemukan bahwa manfaatnya lebih besar daripada kompleksitas performa yang signifikan.

Buatlah jika bisa

Hindari menulis skrip pekerja layanan secara manual. Menulis pekerja layanan dengan tangan memerlukan panduan mengelola resource yang di-cache dan menulis ulang logika yang umum di sebagian besar library pekerja layanan, seperti sebagai Workbox.

Karena itu, karena tech stack internal, kami tidak bisa menggunakan library untuk membuat dan mengelola pekerja layanan kita. Pembelajaran kami di bawah ini terkadang akan mencerminkan hal tersebut. Buka Pitfalls untuk pekerja layanan tidak dihasilkan untuk membaca lebih lanjut.

Tidak semua library kompatibel dengan service worker

Beberapa library JS membuat asumsi yang tidak berfungsi seperti yang diharapkan saat dijalankan oleh pekerja layanan. Sebagai instance, dengan asumsi window atau document tersedia, atau menggunakan API tidak tersedia untuk layanan pekerja (XMLHttpRequest, penyimpanan lokal, dll.). Pastikan library penting apa pun yang Anda butuhkan untuk aplikasi kompatibel dengan pekerja layanan. Untuk PWA khusus ini, kami ingin menggunakan gapi.js untuk autentikasi, tetapi tidak mampu melakukannya karena tidak mendukung pekerja layanan. Penulis perpustakaan juga harus mengurangi atau menghapus asumsi yang tidak perlu tentang konteks JavaScript jika memungkinkan untuk mendukung penggunaan pekerja layanan kasus, seperti menghindari API yang tidak kompatibel dengan pekerja layanan dan menghindari status.

Hindari mengakses IndexedDB selama inisialisasi

Jangan baca IndexedDB saat menginisialisasi skrip pekerja layanan, atau Anda bisa masuk ke dalam 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, sehingga memicu peristiwa Siklus upgrade IDB dari N ke N+1
  5. Karena pengguna memiliki klien lama dengan versi N, proses upgrade pekerja layanan berhenti berfungsi sebagai aktif koneksi masih terbuka ke database versi lama
  6. Pekerja layanan hang, dan tidak pernah menginstal

Dalam kasus kita, cache menjadi tidak valid saat menginstal pekerja layanan, jadi jika pekerja layanan tidak pernah diinstal, pengguna tidak pernah menerima aplikasi yang diupdate.

Membuatnya tangguh

Meskipun skrip pekerja layanan berjalan di latar belakang, skrip itu juga dapat dihentikan kapan saja, bahkan ketika berada di tengah-tengah operasi I/O (jaringan, IDB, dll). Setiap proses yang berjalan lama harus dapat dilanjutkan kapan saja.

Dalam kasus proses sinkronisasi yang mengunggah file besar ke server dan disimpan ke IDB, solusi kami untuk upload sebagian yang terganggu adalah untuk memanfaatkan sistem, menyimpan URL unggahan yang dapat dilanjutkan ke IDB sebelum mengunggah, dan menggunakan URL tersebut untuk unggah jika tidak selesai pertama kali. Juga sebelum operasi I/O yang berjalan lama, {i>state<i} disimpan ke IDB untuk menunjukkan posisi kita untuk setiap {i>record<i}.

Jangan bergantung pada status global

Karena pekerja layanan ada dalam konteks yang berbeda, banyak simbol yang mungkin Anda harapkan tidak saat ini. Banyak kode kami berjalan dalam konteks window, serta dalam konteks pekerja layanan (seperti seperti logging, flag, sinkronisasi, dll.). Kode harus bersifat defensif tentang layanan yang digunakannya, seperti penyimpanan lokal atau cookie. Anda dapat menggunakan globalThis untuk merujuk ke objek global dengan cara yang akan bekerja di semua konteks. Gunakan juga data yang disimpan dalam variabel global dengan hemat, karena tidak ada jaminan kapan skrip akan dihentikan dan negara bagian dikeluarkan.

Pengembangan lokal

Komponen utama pekerja layanan adalah meng-cache resource secara lokal. Namun, selama pengembangan adalah kebalikan yang tepat dari keinginan Anda, terutama jika update dilakukan dengan lambat. Anda masih ingin pekerja server diinstal sehingga Anda bisa men-debug masalah dengannya atau bekerja dengan API lain seperti sinkronisasi latar belakang, atau notifikasi. Di Chrome, Anda dapat mencapai proses ini melalui Chrome DevTools dengan mengaktifkan kotak centang Abaikan untuk jaringan (panel Application > Service worker) di selain mengaktifkan kotak centang Nonaktifkan cache di panel Jaringan untuk juga menonaktifkan cache memori. Untuk mencakup lebih banyak browser, kami memilih solusi lain dengan termasuk tanda untuk menonaktifkan penyimpanan cache di pekerja layanan kami yang diaktifkan secara default pada build yang berbeda. Hal ini memastikan bahwa developer selalu mendapatkan perubahan terbaru tanpa masalah penyimpanan dalam cache. Penting Anda perlu menyertakan header Cache-Control: no-cache juga untuk mencegah browser agar tidak menyimpan aset apa pun dalam cache.

Mercusuar

Lighthouse menyediakan sejumlah proses debug berguna untuk PWA. Alat ini memindai situs dan menghasilkan laporan yang mencakup PWA, performa, aksesibilitas, SEO, dan praktik terbaik lainnya. Sebaiknya jalankan Lighthouse secara berkelanjutan integrasi untuk memberi tahu Anda jika Anda melanggar salah satu kriteria untuk menjadi PWA. Ini sebenarnya pernah terjadi, di mana pekerja layanan tidak menginstal dan kita tidak menyadarinya sebelum melakukan proses produksi. Memiliki Lighthouse sebagai bagian dari CI kita seharusnya mencegah hal itu.

Mendukung continuous delivery

Karena pekerja layanan dapat mengupdate secara otomatis, pengguna tidak memiliki kemampuan untuk membatasi upgrade. Ini secara signifikan mengurangi jumlah klien {i>out-date<i}. Saat pengguna membuka aplikasi kita, pekerja layanan akan melayani klien lama ketika aplikasi mengunduh klien baru dengan lambat. Setelah klien baru diunduh, ia akan meminta pengguna untuk memuat ulang laman guna mengakses fitur baru. Meskipun jika pengguna mengabaikan permintaan ini, di saat berikutnya mereka menyegarkan halaman, mereka akan menerima versi klien. Akibatnya, cukup sulit bagi pengguna untuk menolak update dalam sebaik mungkin untuk aplikasi iOS/Android.

Kami dapat meluncurkan perubahan backend yang dapat menyebabkan gangguan dengan waktu migrasi yang sangat singkat untuk dengan klien besar. Biasanya, kami akan memberikan waktu satu bulan bagi pengguna untuk memberikan {i>update<i} ke klien yang lebih baru sebelum melakukan perubahan yang dapat menyebabkan gangguan. Karena aplikasi akan melayani meskipun sudah tidak berlaku, aplikasi sebenarnya memungkinkan bagi klien yang lebih lama ada di luar sana jika pengguna tidak membuka aplikasi untuk waktu yang lama. Di iOS, pekerja layanan diusir setelah beberapa minggu jadi hal ini tidak terjadi. Untuk Android, masalah ini dapat dimitigasi dengan tidak menayangkan iklan saat kedaluwarsa, atau kedaluwarsa secara manual setelah beberapa minggu. Dalam praktiknya, kita tidak pernah menemui masalah dari klien yang sudah usang. Seberapa ketat tim tertentu ingin berada di sini bergantung pada penggunaan spesifik mereka Namun, 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 yang diperlukan untuk mengakses nilai cookie guna membuat token untuk mengautentikasi permintaan API pihak pertama. Di pekerja layanan, API sinkron seperti document.cookies tidak tersedia. Anda selalu bisa mengirimkan ke klien aktif (berjendela) dari pekerja layanan untuk meminta nilai cookie, meskipun pekerja layanan dapat berjalan di latar belakang tanpa klien berjendela tersedia, seperti saat sinkronisasi latar belakang. Untuk mengatasi hal ini, kita membuat titik akhir pada server frontend yang hanya 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 tidak diperlukan lagi oleh {i>browser<i} yang mendukungnya, karena 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 pekerja layanan menginstal semua file aplikasi statis selama Fase install, yang memungkinkan klien mencapai cache Cache Storage API secara langsung untuk semua kunjungan selanjutnya . Pekerja layanan hanya diinstal saat browser mendeteksi bahwa layanan skrip worker telah berubah, jadi kita harus memastikan bahwa file skrip pekerja layanan itu sendiri berubah sewaktu-waktu ketika file {i>cache<i} berubah. Kita melakukannya secara manual dengan menyematkan sebuah {i>hash <i}dari fileset resource statis dalam skrip pekerja layanan, sehingga setiap rilis menghasilkan file JavaScript pekerja layanan. 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')));

Ini bisa menyulitkan pengujian karena Anda perlu meniru pemicu peristiwa, objek peristiwa, menunggu callback respondWith(), lalu tunggu promise, sebelum akhirnya menyatakan hasilnya. Channel 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 skrip pekerja layanan, kami mempertahankan pekerja layanan inti skrip sebaik mungkin, memisahkan sebagian besar implementasi ke dalam modul lain. Sejak file-file itu hanyalah modul JS standar, mereka bisa lebih mudah diuji unit dengan pengujian standar library.

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 mencari tahu cara menghubungi kami: