Şimdiye kadar Cache
arayüzünde yalnızca bahsediliyor ve
küçük kod snippet'leri gösteriliyordu.
Service Worker'ları verimli bir şekilde kullanmak için bir veya daha fazla önbelleğe alma stratejisi benimsemeniz gerekir. Bunun için Cache
arayüzüne aşina olmanız gerekir.
Önbelleğe alma stratejisi, hizmet çalışanının fetch
etkinliği ile Cache
arayüzü arasındaki etkileşimdir.
Önbelleğe alma stratejisinin nasıl yazıldığı değişiklik gösterir. Örneğin, statik öğe isteklerinin dokümanlardan farklı şekilde işlenmesi tercih edilebilir ve bu, önbelleğe alma stratejisinin nasıl oluşturulacağını etkiler.
Stratejilere geçmeden önce, Cache
arayüzünün ne olmadığı ve ne olduğu hakkında konuşalım ve Service Worker önbelleklerini yönetmek için sunduğu yöntemlerden bazılarını kısaca özetleyelim.
Cache
arayüzü ile HTTP önbelleği karşılaştırması
Daha önce Cache
arayüzüyle hiç çalışmadıysanız bu arayüzün HTTP önbelleğiyle aynı veya en azından HTTP önbelleğiyle ilişkili olduğunu düşünmek cazip gelebilir. Bu doğru değildir.
Cache
arayüzü, HTTP önbelleğinden tamamen ayrı bir önbelleğe alma mekanizmasıdır.- HTTP önbelleğini etkilemek için kullandığınız
Cache-Control
yapılandırması,Cache
arayüzünde hangi öğelerin depolanacağı konusunda herhangi bir etkiye sahip değildir.
Tarayıcı önbelleklerini katmanlı olarak düşünebiliriz. HTTP önbelleği, HTTP üst bilgilerinde ifade edilen yönergelere sahip anahtar/değer çiftleri tarafından çalıştırılan alt düzey bir önbellektir.
Cache
arayüzü ise buna karşılık bir JavaScript API tarafından çalıştırılan üst düzey bir önbellektir.
Bu, nispeten basit HTTP anahtar/değer çiftlerini kullanmaya kıyasla daha fazla esneklik sunar ve önbelleğe alma stratejilerini mümkün kılanın yarısıdır.
Hizmet çalışanı önbellekleriyle ilgili bazı önemli API yöntemleri şunlardır:
- Yeni bir
Cache
örneği oluşturmak içinCacheStorage.open
. Cache.add
veCache.put
kullanarak ağ yanıtlarını bir Service Worker önbelleğinde depolayın.Cache
örneğinde önbelleğe alınan yanıtı bulmak içinCache.match
.Cache
örneğinden önbelleğe alınan bir yanıtı kaldırmak içinCache.delete
.
Müşterilerimizden birkaçı aşağıda yer alıyor. Başka faydalı yöntemler de vardır, ancak bu kılavuzun ilerleyen bölümlerinde göreceğiniz temel yöntemler bunlardır.
Mütevazı fetch
etkinliği
Önbelleğe alma stratejisinin diğer yarısı, hizmet çalışanının fetch
etkinliğidir.
Bu dokümanda şu ana kadar "ağ isteklerine müdahale etme" hakkında biraz bilgi edindiniz. Service Worker içindeki fetch
etkinliğinde bu işlemlerin gerçekleştiği yer alır:
// 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;
}
});
Bu, oyuncak bir örneğidir ve iş sırasında bunu görebilirsiniz. Ancak, hizmet çalışanlarının neler yapabileceğine göz atmanıza olanak tanıyan bir örnektir. Yukarıdaki kod, aşağıdakileri yapar:
- Bunun bir resim isteği olup olmadığını öğrenmek için isteğin
destination
özelliğini inceleyin. - Resim, hizmet çalışanı önbelleğindeyse buradan yayınlayın. Aksi takdirde resmi ağdan getirin, yanıtı önbellekte depolayın ve ağ yanıtını döndürün.
- Diğer tüm istekler, önbellekle etkileşime gerek kalmadan hizmet çalışanı üzerinden iletilir.
Bir getirmenin event
nesnesi, her isteğin türünü tanımlamanıza yardımcı olacak bazı yararlı bilgi parçalarını içeren bir request
özelliği içerir:
url
. Bu, şu andafetch
etkinliği tarafından işlenen ağ isteğinin URL'sidir.method
, istek yöntemidir (ör.GET
veyaPOST
).- İsteğin modunu açıklayan
mode
.'navigate'
değeri genellikle HTML dokümanı isteklerini diğer isteklerden ayırt etmek için kullanılır. destination
: İstenen içeriğin türünü, istenen öğenin dosya uzantısının kullanılmasını önleyecek şekilde açıklar.
Aynı şekilde, eşzamansız oyunun adı da bu.
install
etkinliğinin, taahhüt veren bir event.waitUntil
yöntemi sunduğunu ve etkinleştirme işlemine devam etmeden önce bunun çözümlenmesini beklediğini hatırlarsınız.
fetch
etkinliği, eşzamansız bir fetch
isteği veya Cache
arayüzünün match
yöntemi tarafından döndürülen bir yanıtın sonucunu döndürmek için kullanabileceğiniz benzer bir event.respondWith
yöntemi sunar.
Önbelleğe alma stratejileri
Cache
örnekleri ve fetch
etkinlik işleyicisi hakkında biraz bilgi sahibi olduğunuza göre bazı Service Worker önbelleğe alma stratejilerini ayrıntılı olarak incelemeye hazırsınız.
Olasılıklar neredeyse sonsuz olsa da bu kılavuz Workbox'la birlikte sunulan stratejilere bağlı kalacak, böylece Workbox'ın dahili bileşenlerinde neler olup bittiğini anlayabilirsiniz.
Yalnızca önbellek
"Yalnızca Önbellek" adını verdiğimiz basit bir önbelleğe alma stratejisiyle başlayalım. Nedeni, hizmet çalışanı sayfanın kontrolünde olduğunda eşleşen istekler sadece önbelleğe gider. Bu, kalıbın çalışması için önbelleğe alınan tüm öğelerin önceden önbelleğe alınması gerektiği ve bu öğelerin, hizmet çalışanı güncellenene kadar önbellekte hiçbir zaman güncellenmemesi gerektiği anlamına gelir.
// 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;
}
});
Yukarıda, bir öğe dizisi yükleme sırasında önbelleğe alınır.
Service Worker getirmeleri işlediğinde, fetch
etkinliği tarafından işlenen istek URL'sinin önceden önbelleğe alınmış öğeler dizisinde olup olmadığını kontrol ederiz.
Böyle bir durumda kaynağı önbellekten alır ve ağı atlarız.
Diğer istekler ağa ve yalnızca ağa geçer.
Bu stratejinin nasıl uygulandığını görmek için konsolunuz açıkken bu demoya göz atın.
Yalnızca ağ
"Yalnızca Önbellek"in tersi "Yalnızca Ağ"dır. Burada istek, bir hizmet çalışanı aracılığıyla, hizmet çalışanı önbelleğiyle herhangi bir etkileşim olmadan ağa iletilir. Bu, içeriğin güncel olmasını sağlamak (işaretlemeyi düşünün) için iyi bir stratejidir. Ancak bunun karşılığında, bu strateji kullanıcı çevrimdışı olduğunda asla çalışmayacaktır.
Bir isteğin ağa iletildiğinden emin olmak, eşleşen bir istek için event.respondWith
numaralı telefonu aramamanız anlamına gelir.
Ağa iletmek istediğiniz isteklerin açıkça belirtilmesini istiyorsanız fetch
etkinliği geri çağırma işlevinizde boş bir return;
değerini ekleyebilirsiniz.
Önbelleğe alınmamış istekler için "Yalnızca Önbellek" strateji demosunda bu işlem yapılır.
Önce önbelleğe alın, ağa geri döner
Bu stratejide işler biraz daha karışır. Eşleşen istekler için süreç şu şekilde işler:
- İstek önbelleğe alınır. Öğe önbellekteyse buradan yayınlayın.
- İstek önbellekte değilse ağa gidin.
- Ağ isteği tamamlandıktan sonra bunu önbelleğe ekleyin, ardından ağdan yanıtı döndürün.
Bu stratejinin örneğini canlı bir demoda test edebilirsiniz:
// 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;
}
});
Bu örnekte yalnızca resimler ele alınsa da bu, özellikle karma sürümler başta olmak üzere tüm statik öğelere (CSS, JavaScript, resimler ve yazı tipleri gibi) uygulamak için mükemmel bir stratejidir. HTTP önbelleğinin başlatabileceği içerik güncelliği kontrollerini sunucuyla sekteye uğratarak sabit öğelerin hızını artırır. Daha da önemlisi, önbelleğe alınan tüm öğeler çevrimdışı kullanılabilir olur.
Önce ağ, önbelleğe alma
"Önce ağ, sonra ağ, ikincisi" ayarını yaparsanız sonuçta "Önce ağ, sonra önbellek" stratejisi kalırsınız:
- Bir istek için önce ağa gider ve yanıtı önbelleğe yerleştirirsiniz.
- Daha sonra çevrimdışı olursanız önbellekte o yanıtın en son sürümüne geri dönersiniz.
Bu strateji, çevrimiçi durumdayken bir kaynağın en son sürümüne sahip olmak ve kullanılabilir en son sürüme çevrimdışı erişim vermek istediğinizde HTML veya API istekleri için idealdir. HTML isteklerine uygulandığında bu durum aşağıdaki gibi görünebilir:
// 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;
}
});
Bunu bir demoda deneyebilirsiniz. Önce sayfaya gidin. HTML yanıtının önbelleğe alınmadan önce yeniden yüklenmesi gerekebilir. Ardından geliştirici araçlarınızda çevrimdışı bağlantı simüle edin ve sayfayı yeniden yükleyin. Kullanılabilir son sürüm, önbellekten anında sunulur.
Çevrimdışı kapasitenin önemli olduğu, ancak bu kapasite ile bir işaretleme veya API verisinin en son sürümüne erişim arasında denge kurmanız gerektiği durumlarda, "Önce ağ, sonra önbellek", bu hedefe ulaşmanızı sağlayan sağlam bir stratejidir.
Eski-ancak-tekrar doğrula
Şimdiye kadar ele aldığımız stratejiler arasında "Eski değeri yeniden doğrula" seçeneği en karmaşık olanıdır. Bu, bazı yönlerden son iki stratejiye benzer, ancak prosedür hem bir kaynak için erişim hızına öncelik verir hem de arka planda güncel kalır. Bu stratejinin işleyiş şekli şöyledir:
- Bir öğe için yapılan ilk istekte öğeyi ağdan getirin, önbelleğe yerleştirin ve ağ yanıtını döndürün.
- Sonraki isteklerde, öğeyi önce önbellekten sunun, ardından "arka planda" ağdan yeniden isteyin ve öğenin önbellek girişini güncelleyin.
- Bundan sonraki istekler için önceki adımda önbelleğe yerleştirilmiş ağdan getirilen son sürümü alırsınız.
Bu, güncel kalmak için önemli olan biraz önem taşıyan, ancak hayati önem taşımayan konular için mükemmel bir stratejidir. Öğeleri, bir sosyal medya sitesinin avatarları gibi düşünün. Kullanıcılar bunu yapmaya başladıklarında güncellerler, ancak her istekte en son sürüm şart değildir.
// 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;
}
});
Özellikle tarayıcınızın geliştirici araçlarındaki ağ sekmesine ve CacheStorage
görüntüleyicisine (tarayıcınızın geliştirici araçlarında böyle bir araç varsa) dikkat ederseniz bu işlemin
başka bir canlı demoda görebilirsiniz.
Çalışma Kutusu'na geçiyoruz.
Bu belge, Service Worker'ın API'si ve ilgili API'lerle ilgili incelememizi özetlemiştir.