अब तक, Cache
इंटरफ़ेस के बारे में सिर्फ़ जानकारी दी गई है और इसमें छोटे-छोटे कोड स्निपेट शामिल किए गए हैं.
सर्विस वर्कर को असरदार ढंग से इस्तेमाल करने के लिए, कैश मेमोरी में सेव करने की एक या उससे ज़्यादा रणनीतियों को अपनाना ज़रूरी है.
इसके लिए, Cache
इंटरफ़ेस की थोड़ी जानकारी होना ज़रूरी है.
कैश मेमोरी की रणनीति, सर्विस वर्कर के fetch
इवेंट और Cache
इंटरफ़ेस के बीच होने वाला इंटरैक्शन है.
कैश मेमोरी की रणनीति किस तरह लिखी जाएगी, इस पर निर्भर करता है
उदाहरण के लिए, स्टैटिक ऐसेट के अनुरोधों को दस्तावेज़ों की तुलना में अलग तरीके से हैंडल करने की बेहतर सलाह दी जा सकती है
और इससे कैशिंग रणनीति के काम करने के तरीक़े पर असर पड़ता है.
रणनीतियों पर काम शुरू करने से पहले, आइए इस बारे में बात करते हैं कि Cache
इंटरफ़ेस क्या नहीं है, यह क्या है, और सर्विस वर्कर कैश को मैनेज करने के लिए ऑफ़र किए जाने वाले कुछ तरीकों के बारे में जानते हैं.
Cache
इंटरफ़ेस बनाम एचटीटीपी कैश मेमोरी
अगर आपने Cache
इंटरफ़ेस के साथ पहले काम नहीं किया है,
तो हो सकता है कि आप इसे ठीक वैसा ही समझें या कम से कम एचटीटीपी कैश से जुड़ा हो. हालांकि, ऐसा नहीं होता है.
Cache
इंटरफ़ेस, कैश मेमोरी में सेव करने का एक तरीका है. यह एचटीटीपी कैश से पूरी तरह अलग है.- एचटीटीपी कैश मेमोरी को बेहतर बनाने के लिए, आप जिस भी
Cache-Control
कॉन्फ़िगरेशन का इस्तेमाल करते हैं उसका इस बात पर कोई असर नहीं पड़ता किCache
इंटरफ़ेस में कौनसी एसेट सेव की जाएंगी.
इससे ब्राउज़र की कैश मेमोरी को लेयर वाले स्टोरेज के तौर पर समझने में मदद मिलती है. एचटीटीपी कैश मेमोरी, कम लेवल की कैश मेमोरी है. यह की-वैल्यू पेयर से प्रोसेस होती है. इसमें एचटीटीपी हेडर में बताए गए निर्देश होते हैं.
Cache
इंटरफ़ेस, हाई-लेवल कैश मेमोरी है, जो JavaScript API से चलता है.
यह ज़्यादा सुविधाजनक एचटीटीपी की-वैल्यू पेयर
का इस्तेमाल करने के मुकाबले ज़्यादा सुविधा देता है. साथ ही, कैश मेमोरी में सेव करने की रणनीतियों का आधा हिस्सा होता है.
सर्विस वर्कर कैश मेमोरी से जुड़े एपीआई के कुछ अहम तरीके ये हैं:
CacheStorage.open
नयाCache
इंस्टेंस बनाने के लिए.Cache.add
औरCache.put
सर्विस वर्कर कैश मेमोरी में नेटवर्क रिस्पॉन्स को सेव करना.Cache.match
कोCache
इंस्टेंस में कैश मेमोरी में सेव किया गया रिस्पॉन्स ढूंढने के लिए.Cache.delete
किसीCache
इंस्टेंस से कैश मेमोरी में सेव किए गए रिस्पॉन्स को हटाने के लिए.
ये कुछ ही हैं. काम के अन्य तरीके भी हैं, लेकिन ये वही बुनियादी तरीके हैं जिन्हें आपको आगे इस गाइड में इस्तेमाल किया जाएगा.
fetch
का सादगी भरा इवेंट
कैश मेमोरी की रणनीति का दूसरा हिस्सा, सर्विस वर्कर का
fetch
इवेंट होता है.
इस दस्तावेज़ में अब तक, आपने "नेटवर्क के अनुरोधों में रुकावट डालने" के बारे में कुछ सुना है और सर्विस वर्कर के अंदर fetch
इवेंट में ऐसा होता है:
// 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;
}
});
यह खिलौनों का उदाहरण है—औरजिसे आप अपने हिसाब से इस्तेमाल करते हुए देख सकते हैं—लेकिन यह एक ऐसा उदाहरण है जो दिखाता है कि सर्विस वर्कर क्या कर सकते हैं. ऊपर दिया गया कोड इन चीज़ों के बारे में बताता है:
- अनुरोध की
destination
प्रॉपर्टी की जांच करके देखें कि यह इमेज का अनुरोध है या नहीं. - अगर इमेज, सर्विस वर्कर कैश मेमोरी में है, तो उसे वहीं से इस्तेमाल करें. अगर नहीं, तो नेटवर्क से इमेज फ़ेच करें, रिस्पॉन्स को कैश मेमोरी में सेव करें, और नेटवर्क रिस्पॉन्स दें.
- अन्य सभी अनुरोध, सर्विस वर्कर के ज़रिए पास होते हैं. इसमें कैश मेमोरी के साथ कोई इंटरैक्शन नहीं होता.
फ़ेच के event
ऑब्जेक्ट में,
request
प्रॉपर्टी होती है. इससे आपको हर अनुरोध के टाइप का पता लगाने में मदद मिलती है.
url
, यह उस नेटवर्क अनुरोध का यूआरएल है जिसे फ़िलहालfetch
इवेंट मैनेज कर रहा है.method
, अनुरोध का तरीका (उदाहरण के लिए,GET
याPOST
).mode
, जिसमें अनुरोध के मोड की जानकारी दी गई है. आम तौर पर,'navigate'
वैल्यू का इस्तेमाल, एचटीएमएल दस्तावेज़ों के अनुरोधों को दूसरे अनुरोधों से अलग करने के लिए किया जाता है.destination
, जिसमें अनुरोध किए जा रहे कॉन्टेंट के टाइप के बारे में इस तरह से बताया गया है कि अनुरोध की गई ऐसेट के फ़ाइल एक्सटेंशन का इस्तेमाल नहीं किया जा सकता.
एक बार फिर, एसिंक्रोनस नाम गेम का नाम है.
आपको याद होगा कि install
इवेंट, event.waitUntil
का एक ऐसा तरीका ऑफ़र करता है जिसमें प्रॉमिस मिलता है. ऐक्टिवेशन के लिए, इसके ठीक होने का इंतज़ार करता है.
fetch
इवेंट, इसी तरह के event.respondWith
तरीके का इस्तेमाल करता है. इसका इस्तेमाल एसिंक्रोनस fetch
अनुरोध या Cache
इंटरफ़ेस के match
तरीके से मिले रिस्पॉन्स का नतीजा पाने के लिए किया जा सकता है.
कैश मेमोरी में सेव करने की रणनीतियां
अब जब आपको Cache
इंस्टेंस और fetch
इवेंट हैंडलर के बारे में थोड़ी जानकारी मिल गई है, तो इसका मतलब है कि अब आप सर्विस वर्कर को कैश मेमोरी में सेव करने की कुछ रणनीतियों के बारे में जान सकते हैं.
इसमें व्यावहारिक तौर पर बहुत सी संभावनाएं हैं. हालांकि, यह गाइड वर्कबॉक्स के साथ काम करने वाली रणनीतियों पर काम करेगी
सिर्फ़ कैश मेमोरी में सेव किया गया
चलिए, एक आसान कैशिंग रणनीति से शुरुआत करते हैं, जिसे हम "सिर्फ़ कैश" कहते हैं. इसमें बस इतना ही होता है: जब सर्विस वर्कर पेज के कंट्रोल में होता है, तब मेल खाने वाले अनुरोध सिर्फ़ कैश मेमोरी में जाते हैं. इसका मतलब है कि किसी भी कैश मेमोरी में सेव की गई एसेट को पहले से कैश मेमोरी में सेव करना होगा, ताकि पैटर्न काम कर सके और उस एसेट को तब तक कैश मेमोरी में अपडेट न किया जाए, जब तक सर्विस वर्कर अपडेट नहीं किया जाता.
// 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;
}
});
ऊपर, इंस्टॉल के समय एसेट का कलेक्शन पहले से कैश मेमोरी में सेव किया गया है.
जब सर्विस वर्कर फ़ेच को हैंडल करता है,
तब हम यह जांच करते हैं कि fetch
इवेंट से मैनेज किया जाने वाला अनुरोध यूआरएल, पहले से कैश मेमोरी में सेव की गई एसेट की श्रेणी में है या नहीं.
अगर हां, तो हम रिसॉर्स को कैश मेमोरी से लेते हैं और नेटवर्क को छोड़ देते हैं.
दूसरे अनुरोध, नेटवर्क से और सिर्फ़
नेटवर्क से होकर जाते हैं.
इस रणनीति को काम करने के तरीके के बारे में जानने के लिए,
अपना कंसोल खोलकर यह डेमो देखें.
सिर्फ़ नेटवर्क
"सिर्फ़ कैश", "सिर्फ़ नेटवर्क" के उलट है. इसमें सर्विस वर्कर के ज़रिए अनुरोध को सर्विस वर्कर कैश से बिना इंटरैक्शन के नेटवर्क को भेजा जाता है. कॉन्टेंट को अप-टू-डेट रखने (मार्कअप के बारे में सोचें) के लिए यह एक अच्छी रणनीति है. हालांकि, इसमें समस्या यह है कि उपयोगकर्ता के ऑफ़लाइन होने पर यह कभी काम नहीं करेगा.
यह पक्का करने का मतलब है कि अनुरोध नेटवर्क से होकर गुज़रता है, इसका मतलब यह है कि मिलते-जुलते अनुरोध के लिए event.respondWith
को कॉल न करें.
अगर आपको साफ़ तौर पर टिप्पणी करनी है, तो
fetch
इवेंट कॉलबैक में उन अनुरोधों के लिए खाली return;
स्लैप करें जिन्हें नेटवर्क से भेजना है.
ऐसा उन अनुरोधों के लिए "सिर्फ़ कैश" रणनीति के डेमो में होता है जिन्हें पहले से कैश मेमोरी में सेव नहीं किया गया है.
पहले कैश मेमोरी में सेव करें, वापस नेटवर्क पर आएं
यह रणनीति ऐसी है, जहां चीज़ें थोड़ी और शामिल हो जाती हैं. मिलते-जुलते अनुरोधों के लिए, प्रोसेस इस तरह से होती है:
- अनुरोध कैश मेमोरी में पहुंच जाता है. अगर एसेट कैश मेमोरी में मौजूद है, तो वहां से इसे दिखाया जा सकता है.
- अगर अनुरोध कैश मेमोरी में नहीं है, तो नेटवर्क पर जाएं.
- नेटवर्क से जुड़ा अनुरोध पूरा होने के बाद, उसे कैश मेमोरी में जोड़ें. इसके बाद, नेटवर्क से जवाब दें.
यहां रणनीति का एक उदाहरण दिया गया है, जिसे लाइव डेमो में आज़माया जा सकता है:
// 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;
}
});
हालांकि, इस उदाहरण में सिर्फ़ इमेज शामिल हैं, लेकिन सभी स्टैटिक एसेट (जैसे कि सीएसएस, JavaScript, इमेज, और फ़ॉन्ट) पर इसे लागू करना एक बेहतर रणनीति है. खास तौर पर, हैश वर्शन वाले एसेट पर. यह ऐसी ऐसेट की स्पीड को बढ़ाने में मदद करता है जिनमें बदलाव न किया जा सकता हो. इसके लिए, सर्वर की मदद से कॉन्टेंट के अपडेट होने की जांच करते समय एचटीटीपी कैश मेमोरी को चालू किया जा सकता है. ज़्यादा ज़रूरी यह है कि कैश मेमोरी में सेव की गई कोई भी ऐसेट, ऑफ़लाइन उपलब्ध होगी.
पहले नेटवर्क का इस्तेमाल करें, कैश मेमोरी में वापस जाएं
अगर आपको "पहले कैश मेमोरी में सेव करें, फिर नेटवर्क के हिसाब से दूसरे नेटवर्क पर" को फ़्लिप करना है, तो "नेटवर्क पहले, कैश मेमोरी में सेव करने" की रणनीति चुनी गई है, जो यह कुछ ऐसा लगता है:
- आपको किसी अनुरोध के लिए पहले नेटवर्क पर जाना होता है और रिस्पॉन्स को कैश मेमोरी में डालना होता है.
- अगर आप बाद में कभी ऑफ़लाइन रहते हैं, तो कैश में उस जवाब के सबसे नए वर्शन पर वापस चले जाते हैं.
यह रणनीति एचटीएमएल या एपीआई अनुरोधों के लिए तब सबसे बढ़िया है, जब ऑनलाइन रहते हुए, आपको किसी संसाधन का सबसे नया वर्शन चाहिए, लेकिन आपको सबसे हाल में उपलब्ध वर्शन को ऑफ़लाइन ऐक्सेस देना हो. यहां बताया गया है कि एचटीएमएल के लिए अनुरोध लागू करने पर यह कैसा दिख सकता है:
// 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;
}
});
डेमो में जाकर, इसे आज़माया जा सकता है. सबसे पहले, पेज पर जाएं. कैश मेमोरी में एचटीएमएल रिस्पॉन्स डालने से पहले, आपको पेज को फिर से लोड करना पड़ सकता है. इसके बाद, अपने डेवलपर टूल में ऑफ़लाइन कनेक्शन को सिम्युलेट करें और फिर से लोड करें. आखिरी वर्शन, कैश मेमोरी से तुरंत उपलब्ध हो जाता है.
ऐसी स्थितियों में जहां ऑफ़लाइन क्षमता ज़रूरी है, लेकिन आपको उस क्षमता को छोटे से मार्कअप या एपीआई डेटा के सबसे हाल के वर्शन के ऐक्सेस के साथ संतुलित करना होगा. "नेटवर्क पहले, कैश सेकंड" एक मज़बूत रणनीति है जो इस लक्ष्य को हासिल करती है.
फिर से पुष्टि करते समय पुरानी जानकारी
अब तक हमने जिन रणनीतियों पर बात की है उनमें से, "दोबारा पुष्टि करने के दौरान की गई पुरानी जानकारी" सबसे मुश्किल है. कुछ मामलों में यह पिछली दो रणनीतियों की तरह ही है, लेकिन इस प्रोसेस में संसाधन के ऐक्सेस की स्पीड को प्राथमिकता दी जाती है. साथ ही, इसे बैकग्राउंड में अप-टू-डेट रखा जाता है. यह रणनीति कुछ इस तरह की है:
- किसी एसेट के लिए पहले अनुरोध पर, उसे नेटवर्क से फ़ेच करें, उसे कैश मेमोरी में डालें, और नेटवर्क रिस्पॉन्स दें.
- बाद के अनुरोधों पर, पहले कैश मेमोरी से एसेट का इस्तेमाल करें, फिर "बैकग्राउंड में", नेटवर्क से उसका फिर से अनुरोध करें और एसेट की कैश एंट्री अपडेट करें.
- इसके बाद के अनुरोधों के लिए, आपको नेटवर्क से फ़ेच किया गया पिछला वर्शन मिलेगा जिसे पिछले चरण में कैश मेमोरी में रखा गया था.
यह उन चीज़ों के लिए एक बेहतरीन रणनीति है जो अप-टू-डेट रहने में कुछ तरह की हैं, लेकिन ज़रूरी नहीं हैं. किसी सोशल मीडिया साइट के लिए अवतार जैसी चीज़ों के बारे में सोचें. जब लोग YouTube का इस्तेमाल करते हैं, तो वे अपडेट हो जाते हैं. हालांकि, हर अनुरोध के लिए नया वर्शन ज़रूरी नहीं होता.
// 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;
}
});
इसे किसी दूसरे लाइव डेमो में देखा जा सकता है. खास तौर पर, जब ब्राउज़र के डेवलपर टूल के नेटवर्क टैब और उसके CacheStorage
व्यूअर पर ध्यान दिया जा रहा हो (अगर आपके ब्राउज़र के डेवलपर टूल में ऐसा कोई टूल है).
Workbox की ओर बढ़ें!
इस दस्तावेज़ में, सर्विस वर्कर के एपीआई और इससे जुड़े एपीआई की समीक्षा पूरी हो गई है. इसका मतलब है कि आपने वर्कबॉक्स के साथ काम करने के लिए, सर्विस वर्कर का सीधे तौर पर इस्तेमाल करने के तरीके के बारे में पूरी जानकारी ले ली है!