Beberapa situs web mungkin perlu berkomunikasi dengan pekerja layanan tanpa perlu mendapatkan informasi tentang hasilnya. Berikut beberapa contohnya:
- Halaman mengirim daftar URL kepada pekerja layanan untuk pengambilan data, sehingga saat pengguna mengklik menghubungkan subresource dokumen atau halaman sudah tersedia di cache, sehingga navigasi jauh lebih cepat.
- Halaman ini meminta pekerja layanan untuk mengambil dan meng-cache serangkaian artikel teratas, untuk memilikinya tersedia untuk tujuan offline.
Pendelegasian jenis tugas non-kritis ini kepada pekerja layanan bermanfaat untuk membebaskan untuk menangani tugas yang lebih mendesak seperti merespons interaksi pengguna dengan lebih baik.
Dalam panduan ini, kita akan mempelajari cara menerapkan teknik komunikasi satu arah dari halaman untuk pekerja layanan dengan menggunakan API browser standar dan pustaka Workbox. Kita akan menyebut jenis kasus penggunaan cache imperatif.
Kasus produksi
1-800-Flowers.com menerapkan cache imperatif (pengambilan data) dengan pekerja layanan melalui
postMessage()
untuk mengambil data
item teratas di halaman kategori untuk mempercepat navigasi berikutnya ke halaman detail produk.
Dia menggunakan pendekatan campuran untuk memutuskan item mana yang akan diambil sebelumnya:
- Pada waktu pemuatan halaman, mereka meminta pekerja layanan untuk mengambil data JSON untuk 9 item teratas, dan menambahkan objek respons yang dihasilkan ke cache.
- Untuk item lainnya, mereka mendengarkan
mouseover
peristiwa, sehingga saat pengguna menggerakkan kursor ke atas item, mereka dapat memicu pengambilan resource sesuai "permintaan".
Klien menggunakan Cache API untuk menyimpan JSON respons:
Saat pengguna mengeklik item, data JSON yang terkait dengannya dapat diambil dari {i>cache<i}, tanpa perlu masuk ke jaringan, membuat navigasi menjadi lebih cepat.
Menggunakan Workbox
Workbox menyediakan cara mudah untuk mengirim pesan ke
pekerja layanan, melalui paket workbox-window
, serangkaian modul
yang ditujukan untuk dijalankan dalam konteks jendela. Mereka adalah pelengkap untuk paket {i>Workbox<i} lainnya
yang berjalan di pekerja layanan.
Untuk mengomunikasikan halaman dengan pekerja layanan, terlebih dahulu dapatkan referensi objek Workbox ke pekerja layanan terdaftar:
const wb = new Workbox('/sw.js');
wb.register();
Kemudian Anda bisa langsung mengirim pesan secara deklaratif, tanpa repot mendapatkan pendaftaran, memeriksa aktivasi, atau memikirkan API komunikasi yang mendasarinya:
wb.messageSW({"type": "PREFETCH", "payload": {"urls": ["/data1.json", "data2.json"]}}); });
Pekerja layanan menerapkan pengendali message
untuk
mendengarkan pesan-pesan ini. Secara opsional, {i>respon<i} dapat menghasilkan respons, meskipun dalam kasus seperti ini,
tidak diperlukan:
self.addEventListener('message', (event) => {
if (event.data && event.data.type === 'PREFETCH') {
// do something
}
});
Menggunakan API browser
Jika library Workbox tidak cukup untuk kebutuhan Anda, berikut ini cara menerapkan jendela ke layanan komunikasi pekerja, menggunakan API browser.
postMessage API dapat digunakan untuk membuat mekanisme komunikasi satu arah dari halaman ke pekerja layanan.
Halaman memanggil
postMessage()
di
antarmuka pekerja layanan:
navigator.serviceWorker.controller.postMessage({
type: 'MSG_ID',
payload: 'some data to perform the task',
});
Pekerja layanan menerapkan pengendali message
untuk
mendengarkan pesan-pesan ini.
self.addEventListener('message', (event) => {
if (event.data && event.data.type === MSG_ID) {
// do something
}
});
Atribut {type : 'MSG_ID'}
tidak wajib, tetapi merupakan salah satu cara untuk memungkinkan halaman
mengirim berbagai jenis petunjuk ke pekerja layanan (yaitu, 'untuk mengambil data' vs. 'untuk menghapus
penyimpanan'). Pekerja layanan dapat bercabang ke berbagai jalur eksekusi berdasarkan flag ini.
Jika operasi itu berhasil, pengguna akan bisa mendapatkan manfaat darinya tetapi, jika tidak, itu tidak akan mengubah alur pengguna utama. Misalnya, saat 1-800-Flowers.com mencoba melakukan precache, halaman tidak perlu mengetahui apakah pekerja layanan berhasil atau tidak. Jika ya, maka pengguna akan menikmati navigasi yang lebih cepat. Jika tidak, halaman masih perlu membuka halaman baru. Hanya perlu sedikit lebih lama.
Contoh pengambilan data sederhana
Salah satu penerapan caching imperatif yang paling umum adalah pengambilan data, yang berarti pengambilan sumber daya untuk URL tertentu, sebelum pengguna berpindah ke URL tersebut, untuk mempercepat navigasi.
Ada berbagai cara untuk menerapkan pengambilan data di situs:
- Menggunakan Tag pengambilan data link di halaman: resource disimpan di
cache browser selama lima menit, setelah itu aturan
Cache-Control
normal untuk resource mendaftar. - Melengkapi teknik sebelumnya dengan strategi caching runtime dalam layanan worker untuk memperpanjang masa pengambilan data resource di luar batas ini.
Untuk skenario pengambilan data yang relatif sederhana, seperti pengambilan data dokumen, atau aset tertentu (JS, CSS, dll.), teknik tersebut adalah pendekatan terbaik.
Jika logika tambahan diperlukan, misalnya, mengurai resource pengambilan data (file atau halaman JSON) di untuk mengambil URL internalnya, akan lebih baik untuk mendelegasikan tugas ini sepenuhnya ke pekerja layanan.
Mendelegasikan jenis operasi ini ke pekerja layanan memiliki keuntungan berikut:
- Mengurangi beban pekerjaan pengambilan dan pemrosesan pasca-pengambilan (yang akan diperkenalkan nanti) ke thread sekunder. Dengan melakukan hal ini, thread utama akan bebas menangani tugas yang lebih penting tugas seperti merespons interaksi pengguna.
- Memungkinkan beberapa klien (mis. tab) menggunakan kembali fungsi umum, dan bahkan memanggil layanan secara bersamaan tanpa memblokir thread utama.
Mengambil halaman detail produk
Pertama kali menggunakan postMessage()
pada
antarmuka pekerja layanan dan meneruskan array URL ke cache:
navigator.serviceWorker.controller.postMessage({
type: 'PREFETCH',
payload: {
urls: [
'www.exmaple.com/apis/data_1.json',
'www.exmaple.com/apis/data_2.json',
],
},
});
Di pekerja layanan, terapkan pengendali message
untuk
mencegat dan memproses pesan yang dikirim oleh tab aktif mana pun:
addEventListener('message', (event) => {
let data = event.data;
if (data && data.type === 'PREFETCH') {
let urls = data.payload.urls;
for (let i in urls) {
fetchAsync(urls[i]);
}
}
});
Pada kode sebelumnya, kami memperkenalkan fungsi bantuan kecil yang disebut fetchAsync()
untuk melakukan iterasi pada
rangkaian URL dan mengeluarkan permintaan pengambilan untuk masing-masing URL:
async function fetchAsync(url) {
// await response of fetch call
let prefetched = await fetch(url);
// (optionally) cache resources in the service worker storage
}
Saat respons diperoleh, Anda dapat mengandalkan header caching resource. Di banyak kasus
meskipun, seperti di halaman detail produk, resource tidak di-cache (yang berarti, resource memiliki
Cache-control
dari no-cache
). Dalam kasus seperti ini Anda dapat
mengganti perilaku ini, dengan
menyimpan resource yang diambil dalam cache pekerja layanan. Fungsi ini memiliki manfaat tambahan karena memungkinkan
file untuk ditayangkan dalam skenario offline.
Di luar data JSON
Setelah data JSON diambil dari endpoint server, data JSON sering kali berisi URL lain yang juga pengambilan data, seperti gambar atau data endpoint lainnya yang dikaitkan dengan level pertama layanan otomatis dan data skalabel.
Katakanlah dalam contoh kita, data JSON yang ditampilkan adalah informasi situs belanja bahan makanan:
{
"productName": "banana",
"productPic": "https://cdn.example.com/product_images/banana.jpeg",
"unitPrice": "1.99"
}
Ubah kode fetchAsync()
untuk melakukan iterasi pada daftar produk dan meng-cache banner besar untuk
setiap elemen tersebut:
async function fetchAsync(url, postProcess) {
// await response of fetch call
let prefetched = await fetch(url);
//(optionally) cache resource in the service worker cache
// carry out the post fetch process if supplied
if (postProcess) {
await postProcess(prefetched);
}
}
async function postProcess(prefetched) {
let productJson = await prefetched.json();
if (productJson && productJson.product_pic) {
fetchAsync(productJson.product_pic);
}
}
Anda dapat menambahkan beberapa penanganan pengecualian seputar kode ini untuk situasi seperti 404. Tetapi keuntungan menggunakan pekerja layanan untuk pengambilan data adalah bahwa itu bisa gagal tanpa banyak konsekuensi ke halaman dan thread utama. Anda mungkin juga memiliki logika yang lebih rumit dalam konten yang telah diambil sebelumnya, membuatnya lebih fleksibel dan dipisahkan dengan data penanganannya. Langit adalah batasnya.
Kesimpulan
Dalam artikel ini, kita membahas kasus penggunaan umum komunikasi satu arah antara halaman dan layanan worker: cache imperatif. Contoh yang dibahas hanya dimaksudkan untuk menunjukkan salah satu cara menggunakan pola ini dan pendekatan yang sama juga dapat diterapkan pada kasus penggunaan lainnya, misalnya, menyimpan cache artikel on demand untuk konsumsi offline, bookmark, dan lainnya.
Untuk pola komunikasi pekerja layanan dan halaman lainnya, lihat:
- Update siaran: Memanggil halaman dari pekerja layanan untuk menginformasikan tentang update penting (misalnya, versi baru aplikasi web tersedia).
- Komunikasi dua arah: Mendelegasikan tugas kepada pekerja layanan (mis. download yang berat), dan memberi tahu halaman tentang kemajuannya.