Yang telah dipelajari tim Buletin tentang pekerja layanan saat mengembangkan PWA.
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:
- 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
, sehingga memicu peristiwa Siklus upgrade IDB dari N ke N+1 - Karena pengguna memiliki klien lama dengan versi N, proses upgrade pekerja layanan berhenti berfungsi sebagai aktif koneksi masih terbuka ke database versi lama
- 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: