सर्विस वर्कर कैशिंग के लिए रणनीतियां

अब तक, 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;
  }
});

यह खिलौनों का उदाहरण है—औरजिसे आप अपने हिसाब से इस्तेमाल करते हुए देख सकते हैं—लेकिन यह एक ऐसा उदाहरण है जो दिखाता है कि सर्विस वर्कर क्या कर सकते हैं. ऊपर दिया गया कोड इन चीज़ों के बारे में बताता है:

  1. अनुरोध की destination प्रॉपर्टी की जांच करके देखें कि यह इमेज का अनुरोध है या नहीं.
  2. अगर इमेज, सर्विस वर्कर कैश मेमोरी में है, तो उसे वहीं से इस्तेमाल करें. अगर नहीं, तो नेटवर्क से इमेज फ़ेच करें, रिस्पॉन्स को कैश मेमोरी में सेव करें, और नेटवर्क रिस्पॉन्स दें.
  3. अन्य सभी अनुरोध, सर्विस वर्कर के ज़रिए पास होते हैं. इसमें कैश मेमोरी के साथ कोई इंटरैक्शन नहीं होता.

फ़ेच के 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; स्लैप करें जिन्हें नेटवर्क से भेजना है. ऐसा उन अनुरोधों के लिए "सिर्फ़ कैश" रणनीति के डेमो में होता है जिन्हें पहले से कैश मेमोरी में सेव नहीं किया गया है.

पहले कैश मेमोरी में सेव करें, वापस नेटवर्क पर आएं

अगर कैश मेमोरी में नहीं है, तो पेज से सर्विस वर्कर, कैश मेमोरी, और फिर नेटवर्क के फ़्लो को दिखाता है.

यह रणनीति ऐसी है, जहां चीज़ें थोड़ी और शामिल हो जाती हैं. मिलते-जुलते अनुरोधों के लिए, प्रोसेस इस तरह से होती है:

  1. अनुरोध कैश मेमोरी में पहुंच जाता है. अगर एसेट कैश मेमोरी में मौजूद है, तो वहां से इसे दिखाया जा सकता है.
  2. अगर अनुरोध कैश मेमोरी में नहीं है, तो नेटवर्क पर जाएं.
  3. नेटवर्क से जुड़ा अनुरोध पूरा होने के बाद, उसे कैश मेमोरी में जोड़ें. इसके बाद, नेटवर्क से जवाब दें.

यहां रणनीति का एक उदाहरण दिया गया है, जिसे लाइव डेमो में आज़माया जा सकता है:

// 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, इमेज, और फ़ॉन्ट) पर इसे लागू करना एक बेहतर रणनीति है. खास तौर पर, हैश वर्शन वाले एसेट पर. यह ऐसी ऐसेट की स्पीड को बढ़ाने में मदद करता है जिनमें बदलाव न किया जा सकता हो. इसके लिए, सर्वर की मदद से कॉन्टेंट के अपडेट होने की जांच करते समय एचटीटीपी कैश मेमोरी को चालू किया जा सकता है. ज़्यादा ज़रूरी यह है कि कैश मेमोरी में सेव की गई कोई भी ऐसेट, ऑफ़लाइन उपलब्ध होगी.

पहले नेटवर्क का इस्तेमाल करें, कैश मेमोरी में वापस जाएं

नेटवर्क उपलब्ध न होने पर, यह पेज से सर्विस वर्कर, नेटवर्क, और फिर कैश मेमोरी में जाने का फ़्लो दिखाता है.

अगर आपको "पहले कैश मेमोरी में सेव करें, फिर नेटवर्क के हिसाब से दूसरे नेटवर्क पर" को फ़्लिप करना है, तो "नेटवर्क पहले, कैश मेमोरी में सेव करने" की रणनीति चुनी गई है, जो यह कुछ ऐसा लगता है:

  1. आपको किसी अनुरोध के लिए पहले नेटवर्क पर जाना होता है और रिस्पॉन्स को कैश मेमोरी में डालना होता है.
  2. अगर आप बाद में कभी ऑफ़लाइन रहते हैं, तो कैश में उस जवाब के सबसे नए वर्शन पर वापस चले जाते हैं.

यह रणनीति एचटीएमएल या एपीआई अनुरोधों के लिए तब सबसे बढ़िया है, जब ऑनलाइन रहते हुए, आपको किसी संसाधन का सबसे नया वर्शन चाहिए, लेकिन आपको सबसे हाल में उपलब्ध वर्शन को ऑफ़लाइन ऐक्सेस देना हो. यहां बताया गया है कि एचटीएमएल के लिए अनुरोध लागू करने पर यह कैसा दिख सकता है:

// 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;
  }
});

डेमो में जाकर, इसे आज़माया जा सकता है. सबसे पहले, पेज पर जाएं. कैश मेमोरी में एचटीएमएल रिस्पॉन्स डालने से पहले, आपको पेज को फिर से लोड करना पड़ सकता है. इसके बाद, अपने डेवलपर टूल में ऑफ़लाइन कनेक्शन को सिम्युलेट करें और फिर से लोड करें. आखिरी वर्शन, कैश मेमोरी से तुरंत उपलब्ध हो जाता है.

ऐसी स्थितियों में जहां ऑफ़लाइन क्षमता ज़रूरी है, लेकिन आपको उस क्षमता को छोटे से मार्कअप या एपीआई डेटा के सबसे हाल के वर्शन के ऐक्सेस के साथ संतुलित करना होगा. "नेटवर्क पहले, कैश सेकंड" एक मज़बूत रणनीति है जो इस लक्ष्य को हासिल करती है.

फिर से पुष्टि करते समय पुरानी जानकारी

यह पेज से सर्विस वर्कर, कैश मेमोरी, और फिर नेटवर्क से कैश मेमोरी पर जाने का फ़्लो दिखाता है.

अब तक हमने जिन रणनीतियों पर बात की है उनमें से, "दोबारा पुष्टि करने के दौरान की गई पुरानी जानकारी" सबसे मुश्किल है. कुछ मामलों में यह पिछली दो रणनीतियों की तरह ही है, लेकिन इस प्रोसेस में संसाधन के ऐक्सेस की स्पीड को प्राथमिकता दी जाती है. साथ ही, इसे बैकग्राउंड में अप-टू-डेट रखा जाता है. यह रणनीति कुछ इस तरह की है:

  1. किसी एसेट के लिए पहले अनुरोध पर, उसे नेटवर्क से फ़ेच करें, उसे कैश मेमोरी में डालें, और नेटवर्क रिस्पॉन्स दें.
  2. बाद के अनुरोधों पर, पहले कैश मेमोरी से एसेट का इस्तेमाल करें, फिर "बैकग्राउंड में", नेटवर्क से उसका फिर से अनुरोध करें और एसेट की कैश एंट्री अपडेट करें.
  3. इसके बाद के अनुरोधों के लिए, आपको नेटवर्क से फ़ेच किया गया पिछला वर्शन मिलेगा जिसे पिछले चरण में कैश मेमोरी में रखा गया था.

यह उन चीज़ों के लिए एक बेहतरीन रणनीति है जो अप-टू-डेट रहने में कुछ तरह की हैं, लेकिन ज़रूरी नहीं हैं. किसी सोशल मीडिया साइट के लिए अवतार जैसी चीज़ों के बारे में सोचें. जब लोग 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 की ओर बढ़ें!

इस दस्तावेज़ में, सर्विस वर्कर के एपीआई और इससे जुड़े एपीआई की समीक्षा पूरी हो गई है. इसका मतलब है कि आपने वर्कबॉक्स के साथ काम करने के लिए, सर्विस वर्कर का सीधे तौर पर इस्तेमाल करने के तरीके के बारे में पूरी जानकारी ले ली है!