Sampai sekarang, baru ada penyebutan
dan cuplikan kode kecil dari
Antarmuka Cache
.
Untuk menggunakan pekerja layanan secara efektif, Anda perlu mengadopsi satu atau lebih strategi {i>caching<i},
yang memerlukan sedikit pemahaman tentang antarmuka Cache
.
Strategi caching adalah interaksi antara peristiwa fetch
pekerja layanan dan antarmuka Cache
.
Cara penulisan strategi penyimpanan dalam cache bergantung;
misalnya, mungkin lebih baik menangani permintaan untuk aset statis daripada dokumen,
dan hal ini memengaruhi cara
membuat strategi penyimpanan dalam cache.
Sebelum kita membahas strategi,
mari kita luangkan waktu sejenak untuk membahas
apa yang tidak ada di antarmuka Cache
,
dan ikhtisar singkat dari beberapa metode yang ditawarkannya untuk mengelola cache pekerja layanan.
Antarmuka Cache
versus cache HTTP
Jika Anda belum pernah menggunakan antarmuka Cache
,
hal itu mungkin tergoda untuk
menganggapnya sama dengan,
atau setidaknya terkait
dengan {i>cache<i} HTTP. Bukan itu masalahnya.
- Antarmuka
Cache
adalah mekanisme penyimpanan cache yang sepenuhnya terpisah dari cache HTTP. - Apa pun
Cache-Control
yang Anda gunakan untuk memengaruhi cache HTTP tidak berpengaruh pada aset apa yang disimpan di antarmukaCache
.
Hal ini membantu untuk menganggap {i> cache browser<i} sebagai berlapis. Cache HTTP adalah cache tingkat rendah yang didorong oleh key-value pair dengan perintah yang dinyatakan dalam header HTTP.
Sebaliknya, antarmuka Cache
adalah cache tingkat tinggi yang didorong oleh JavaScript API.
Cara ini menawarkan lebih banyak fleksibilitas dibandingkan bila
menggunakan pasangan nilai kunci HTTP yang relatif sederhana,
dan merupakan setengah dari sekian banyak yang
memungkinkan strategi {i>caching<i}.
Beberapa metode API penting seputar cache pekerja layanan adalah:
CacheStorage.open
untuk membuat instanceCache
baru.Cache.add
danCache.put
untuk menyimpan respons jaringan dalam cache pekerja layanan.Cache.match
untuk menemukan respons yang di-cache dalam instanceCache
.Cache.delete
untuk menghapus respons yang di-cache dari instanceCache
.
Ini hanya beberapa di antaranya. Ada metode lain yang berguna, yang akan digunakan nanti dalam panduan ini.
Acara fetch
sederhana
Setengah lainnya dari strategi caching adalah
Peristiwa fetch
.
Sejauh ini dalam dokumentasi ini, Anda telah mendengar sedikit
tentang "mencegatan permintaan jaringan",
dan peristiwa fetch
di dalam pekerja layanan adalah tempat hal ini terjadi:
// Establish a cache name
const cacheName = 'MyFancyCacheName_v1';
self.addEventListener('install', (event) => {
event.waitUntil(caches.open(cacheName));
});
self.addEventListener('fetch', async (event) => {
// Is this a request for an image?
if (event.request.destination === 'image') {
// Open the cache
event.respondWith(caches.open(cacheName).then((cache) => {
// Respond with the image from the cache or from the network
return cache.match(event.request).then((cachedResponse) => {
return cachedResponse || fetch(event.request.url).then((fetchedResponse) => {
// Add the network response to the cache for future visits.
// Note: we need to make a copy of the response to save it in
// the cache and use the original as the request response.
cache.put(event.request, fetchedResponse.clone());
// Return the network response
return fetchedResponse;
});
});
}));
} else {
return;
}
});
Ini adalah contoh mainan—dan yang dapat Anda lihat sendiri—tetapi itu adalah salah satu yang memberikan gambaran sekilas tentang apa yang dapat dilakukan pekerja layanan. Kode di atas melakukan hal berikut:
- Periksa properti
destination
permintaan untuk melihat apakah ini adalah permintaan gambar. - Jika gambar berada di cache pekerja layanan, tayangkan dari sana. Jika tidak, ambil gambar dari jaringan, menyimpan respons dalam {i>cache<i}, dan mengembalikan respons jaringan.
- Semua permintaan lain diteruskan melalui pekerja layanan tanpa interaksi dengan cache.
Objek event
pengambilan berisi
Properti request
informasi yang berguna untuk membantu
Anda mengidentifikasi tipe setiap permintaan:
url
, yaitu URL untuk permintaan jaringan yang saat ini ditangani oleh peristiwafetch
.method
, yang merupakan metode permintaan (mis.,GET
atauPOST
).mode
, yang menjelaskan mode permintaan. Nilai'navigate'
sering digunakan untuk membedakan permintaan dokumen HTML dengan permintaan lainnya.destination
, yang mendeskripsikan jenis konten yang diminta dengan cara yang menghindari penggunaan ekstensi file aset yang diminta.
Sekali lagi, asynchrony adalah nama game.
Anda akan ingat bahwa peristiwa install
menawarkan
event.waitUntil
yang menggunakan promise, dan menunggunya diselesaikan sebelum melanjutkan ke aktivasi.
Peristiwa fetch
menawarkan
Metode event.respondWith
yang dapat digunakan untuk menampilkan hasil
permintaan fetch
atau respons yang ditampilkan oleh antarmuka Cache
Metode match
.
Strategi penyimpanan dalam cache
Setelah Anda sedikit memahami instance Cache
dan pengendali peristiwa fetch
,
Anda siap untuk mempelajari lebih dalam
beberapa strategi {i>caching<i} pekerja layanan.
Sementara kemungkinannya
tidak ada batasnya,
panduan ini akan tetap mengacu pada strategi yang disertakan dengan Workbox,
sehingga Anda bisa mengetahui apa
yang terjadi di internal {i>Workbox<i}.
Cache saja
Mari kita mulai dengan strategi penyimpanan cache sederhana yang akan kita sebut "Hanya Cache". Hanya saja: ketika pekerja layanan mengontrol halaman, permintaan yang sesuai hanya akan masuk ke cache. Artinya, setiap aset yang di-cache harus di-pra-cache agar tersedia agar pola dapat berfungsi, dan aset tersebut tidak akan diperbarui di cache hingga pekerja layanan diperbarui.
// Establish a cache name
const cacheName = 'MyFancyCacheName_v1';
// Assets to precache
const precachedAssets = [
'/possum1.jpg',
'/possum2.jpg',
'/possum3.jpg',
'/possum4.jpg'
];
self.addEventListener('install', (event) => {
// Precache assets on install
event.waitUntil(caches.open(cacheName).then((cache) => {
return cache.addAll(precachedAssets);
}));
});
self.addEventListener('fetch', (event) => {
// Is this one of our precached assets?
const url = new URL(event.request.url);
const isPrecachedRequest = precachedAssets.includes(url.pathname);
if (isPrecachedRequest) {
// Grab the precached asset from the cache
event.respondWith(caches.open(cacheName).then((cache) => {
return cache.match(event.request.url);
}));
} else {
// Go to the network
return;
}
});
Di atas, array aset di-pra-cache pada waktu penginstalan.
Ketika pekerja layanan menangani pengambilan,
kami akan memeriksa apakah URL permintaan yang ditangani oleh peristiwa fetch
ada dalam array aset yang telah disimpan sebelumnya.
Jika demikian, kita mengambil resource dari cache, dan melewati jaringan.
Permintaan lain diteruskan ke jaringan,
dan hanya jaringan.
Untuk melihat cara kerja strategi ini,
lihat demo ini dengan konsol Anda dalam keadaan terbuka.
Khusus jaringan
Kebalikan dari "Cache Only" adalah "Hanya Jaringan", di mana permintaan diteruskan melalui pekerja layanan ke jaringan tanpa interaksi apa pun dengan cache pekerja layanan. Ini adalah strategi yang baik untuk memastikan keaktualan konten (seperti markup), tetapi konsekuensinya adalah, ia tidak akan pernah berfungsi ketika pengguna sedang {i>offline<i}.
Memastikan permintaan melewati jaringan berarti Anda tidak memanggil event.respondWith
untuk permintaan yang cocok.
Jika Anda ingin bersikap eksplisit,
Anda dapat menampar return;
kosong di callback peristiwa fetch
untuk permintaan yang ingin diteruskan ke jaringan.
Inilah yang terjadi di dalam kotak "Cache Only" demo strategi untuk permintaan yang tidak di-pra-cache.
Cache terlebih dahulu, beralih kembali ke jaringan
Strategi ini adalah momen di mana segala sesuatunya menjadi lebih terlibat. Untuk permintaan pencocokan, prosesnya berjalan seperti ini:
- Permintaan mencapai cache. Jika aset berada di cache, tayangkan dari sana.
- Jika permintaan tidak ada dalam cache, buka jaringan.
- Setelah permintaan jaringan selesai, tambahkan ke cache, kemudian mengembalikan respons dari jaringan.
Berikut adalah contoh strategi ini, yang dapat Anda uji demo langsung:
// Establish a cache name
const cacheName = 'MyFancyCacheName_v1';
self.addEventListener('fetch', (event) => {
// Check if this is a request for an image
if (event.request.destination === 'image') {
event.respondWith(caches.open(cacheName).then((cache) => {
// Go to the cache first
return cache.match(event.request.url).then((cachedResponse) => {
// Return a cached response if we have one
if (cachedResponse) {
return cachedResponse;
}
// Otherwise, hit the network
return fetch(event.request).then((fetchedResponse) => {
// Add the network response to the cache for later visits
cache.put(event.request, fetchedResponse.clone());
// Return the network response
return fetchedResponse;
});
});
}));
} else {
return;
}
});
Meskipun contoh ini hanya mencakup gambar, ini adalah strategi yang bagus untuk diterapkan pada semua aset statis (seperti CSS, JavaScript, gambar, dan font), terutama yang memiliki versi {i>hash<i}. Layanan ini menawarkan peningkatan kecepatan untuk aset yang tidak dapat diubah dengan meniadakan pemeriksaan keaktualan konten dengan server yang mungkin dimulai oleh cache HTTP. Yang lebih penting, aset yang di-cache akan tersedia secara offline.
Jaringan terlebih dahulu, beralih kembali ke cache
Jika Anda membalik "Cache pertama, jaringan kedua" di kepalanya, Anda akan mendapati pesan "Jaringan terlebih dahulu, cache kedua" strategi, seperti namanya:
- Anda masuk ke jaringan terlebih dahulu untuk membuat permintaan, dan menempatkan respons di cache.
- Jika Anda kemudian offline, Anda kembali ke versi terbaru dari respons itu dalam {i>cache<i}.
Strategi ini sangat bagus untuk permintaan HTML atau API saat, saat sedang {i>online<i}, Anda ingin versi terbaru dari sumber daya, namun ingin memberikan akses offline ke versi terbaru yang tersedia. Berikut adalah tampilan yang mungkin akan terlihat bila diterapkan ke permintaan untuk HTML:
// Establish a cache name
const cacheName = 'MyFancyCacheName_v1';
self.addEventListener('fetch', (event) => {
// Check if this is a navigation request
if (event.request.mode === 'navigate') {
// Open the cache
event.respondWith(caches.open(cacheName).then((cache) => {
// Go to the network first
return fetch(event.request.url).then((fetchedResponse) => {
cache.put(event.request, fetchedResponse.clone());
return fetchedResponse;
}).catch(() => {
// If the network is unavailable, get
return cache.match(event.request.url);
});
}));
} else {
return;
}
});
Anda dapat mencobanya dalam demo. Pertama, buka halaman. Anda mungkin perlu memuat ulang sebelum tanggapan HTML ditempatkan dalam cache. Kemudian di {i>developer tools<i} Anda, menyimulasikan koneksi offline, lalu muat ulang lagi. Versi terakhir yang tersedia akan langsung disajikan dari cache.
Dalam situasi di mana kemampuan offline itu penting, tetapi Anda perlu menyeimbangkan kemampuan itu dengan akses ke versi terbaru dari sedikit markup atau data API, "Jaringan terlebih dahulu, cache kedua" merupakan strategi mantap yang mencapai sasaran tersebut.
Tidak berlaku saat validasi ulang
Strategi yang telah kita bahas sejauh ini, "Stale-temporary-validate" yang paling kompleks. Hal ini mirip dengan dua strategi terakhir dalam beberapa hal, tetapi prosedurnya memprioritaskan kecepatan akses untuk sumber daya, sambil tetap memperbaruinya di latar belakang. Strategi ini berjalan seperti:
- Pada permintaan pertama untuk aset, ambillah dari jaringan, memasukkannya ke dalam {i>cache<i}, dan mengembalikan respons jaringan.
- Pada permintaan berikutnya, tayangkan aset dari cache terlebih dahulu, lalu "di latar belakang", memintanya lagi dari jaringan dan memperbarui entri cache aset.
- Untuk permintaan setelahnya, Anda akan menerima versi terakhir yang diambil dari jaringan yang ditempatkan di {i>cache<i} pada langkah sebelumnya.
Ini adalah strategi yang sangat bagus untuk hal-hal yang sema penting untuk selalu diperbarui, tetapi tidak penting. Anggap saja hal-hal seperti avatar untuk situs media sosial. Mereka mendapatkan pembaruan ketika pengguna melakukannya, tetapi versi terbaru tidak sepenuhnya diperlukan pada setiap permintaan.
// Establish a cache name
const cacheName = 'MyFancyCacheName_v1';
self.addEventListener('fetch', (event) => {
if (event.request.destination === 'image') {
event.respondWith(caches.open(cacheName).then((cache) => {
return cache.match(event.request).then((cachedResponse) => {
const fetchedResponse = fetch(event.request).then((networkResponse) => {
cache.put(event.request, networkResponse.clone());
return networkResponse;
});
return cachedResponse || fetchedResponse;
});
}));
} else {
return;
}
});
Anda dapat melihat cara kerjanya di
sebuah demo langsung lainnya,
terutama jika Anda memperhatikan tab jaringan
di alat pengembang browser Anda,
dan penampil CacheStorage
(jika alat developer browser Anda memiliki alat tersebut).
Lanjutkan ke Workbox!
Dokumen ini merangkum ulasan kita tentang API pekerja layanan, serta API terkait, yang berarti Anda sudah cukup belajar tentang cara menggunakan pekerja layanan secara langsung untuk mulai mengutak-atik Workbox!