सेवा में है

प्रोग्रेसिव वेब ऐप्लिकेशन का एक मुख्य पहलू यह है कि ये भरोसेमंद होते हैं. ये एसेट को तेज़ी से लोड कर सकते हैं. साथ ही, नेटवर्क की खराब स्थिति में भी, उपयोगकर्ताओं को जोड़े रखते हैं और तुरंत सुझाव/राय देते हैं. यह कैसे हो सकता है? सेवा वर्कर fetch इवेंट का धन्यवाद.

फ़ेच इवेंट

Browser Support

  • Chrome: 40.
  • Edge: 17.
  • Firefox: 44.
  • Safari: 11.1.

Source

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

fetch हैंडलर को किसी ऐप्लिकेशन से सभी अनुरोध मिलते हैं. इनमें यूआरएल और एचटीटीपी हेडर भी शामिल हैं. साथ ही, ऐप्लिकेशन डेवलपर यह तय कर सकता है कि उन्हें कैसे प्रोसेस किया जाए.

सेवा वर्कर, क्लाइंट और नेटवर्क के बीच काम करता है.

आपका सर्विस वर्कर, नेटवर्क को अनुरोध भेज सकता है, पहले से कैश मेमोरी में सेव किए गए जवाब के साथ जवाब दे सकता है या नया जवाब बना सकता है. यह आपको तय करना है. इसका एक आसान सा उदाहरण देखें :

self.addEventListener("fetch", event => {
    console.log(`URL requested: ${event.request.url}`);
});

अनुरोध का जवाब देना

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

किसी इनकमिंग अनुरोध का जवाब देने के लिए, fetch इवेंट हैंडलर में जाकर event.respondWith() को कॉल करें. जैसे:

// fetch event handler in your service worker file
self.addEventListener("fetch", event => {
    const response = .... // a response or a Promise of response
    event.respondWith(response);
});

आपको respondWith() को सिंक्रोनस तरीके से कॉल करना होगा और आपको Response ऑब्जेक्ट दिखाना होगा. हालांकि, फ़ेच इवेंट हैंडलर के खत्म होने के बाद, respondWith() को कॉल नहीं किया जा सकता. जैसे, किसी असाइनोक कॉल में. अगर आपको पूरे जवाब का इंतज़ार करना है, तो respondWith() को एक ऐसा Promise पास किया जा सकता है जो Response के साथ रिज़ॉल्व होता है.

जवाब बनाना

Fetch API की मदद से, अपने JavaScript कोड में एचटीटीपी रिस्पॉन्स बनाए जा सकते हैं. साथ ही, Cache Storage API का इस्तेमाल करके उन रिस्पॉन्स को कैश मेमोरी में सेव किया जा सकता है और उन्हें वेब सर्वर से मिले रिस्पॉन्स की तरह दिखाया जा सकता है.

जवाब बनाने के लिए, एक नया Response ऑब्जेक्ट बनाएं. इसमें, उसके मुख्य हिस्से और विकल्पों को सेट करें. जैसे, स्थिति और हेडर:

const simpleResponse = new Response("Body of the HTTP response");

const options = {
   status: 200,
   headers: {
    'Content-type': 'text/html'
   }
};
const htmlResponse = new Response("<b>HTML</b> content", options)

कैश मेमोरी से जवाब देना

अब आपको सेवा वर्कर से एचटीटीपी रिस्पॉन्स भेजने का तरीका पता है. अब डिवाइस पर ऐसेट सेव करने के लिए, कैश मेमोरी स्टोरेज इंटरफ़ेस का इस्तेमाल करें.

कैश मेमोरी स्टोरेज एपीआई का इस्तेमाल करके, यह देखा जा सकता है कि PWA से मिला अनुरोध कैश मेमोरी में उपलब्ध है या नहीं. अगर उपलब्ध है, तो respondWith() को उससे जवाब दें. इसके लिए, आपको पहले कैश मेमोरी में खोजना होगा. match() फ़ंक्शन, टॉप-लेवल caches इंटरफ़ेस पर उपलब्ध है. यह आपके ऑरिजिन में मौजूद सभी स्टोर या किसी एक ओपन कैश मेमोरी ऑब्जेक्ट को खोजता है.

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

// Global search on all caches in the current origin
caches.match(urlOrRequest).then(response => {
   console.log(response ? response : "It's not in the cache");
});

// Cache-specific search
caches.open("pwa-assets").then(cache => {
  cache.match(urlOrRequest).then(response => {
    console.log(response ? response : "It's not in the cache");
  });
});

कैश मेमोरी में सेव करने की रणनीतियां

सिर्फ़ ब्राउज़र कैश मेमोरी से फ़ाइलें दिखाना, हर तरह के डिवाइसों के लिए कारगर नहीं है. उदाहरण के लिए, उपयोगकर्ता या ब्राउज़र, कैश मेमोरी को मिटा सकता है. इसलिए, आपको अपने PWA के लिए एसेट डिलीवर करने की अपनी रणनीतियां तय करनी चाहिए. आपके पास कैश मेमोरी सेव करने की एक से ज़्यादा रणनीतियां इस्तेमाल करने का विकल्प होता है. अलग-अलग यूआरएल पैटर्न के लिए, अलग-अलग पैरामीटर तय किए जा सकते हैं. उदाहरण के लिए, आपके पास कम से कम यूज़र इंटरफ़ेस (यूआई) एसेट के लिए एक रणनीति, एपीआई कॉल के लिए दूसरी रणनीति, और इमेज और डेटा यूआरएल के लिए तीसरी रणनीति हो सकती है. इसके लिए, ServiceWorkerGlobalScope.onfetch में event.request.url पढ़ें और इसे रेगुलर एक्सप्रेशन या यूआरएल पैटर्न की मदद से पार्स करें. (यह लेख लिखे जाने के समय, यूआरएल पैटर्न की सुविधा सभी प्लैटफ़ॉर्म पर काम नहीं करती).

सबसे आम रणनीतियां ये हैं:

पहले कैश मेमोरी में सेव करें
सबसे पहले कैश मेमोरी में सेव किए गए जवाब को खोजता है. अगर कोई जवाब नहीं मिलता है, तो नेटवर्क से जवाब मांगता है.
नेटवर्क फ़र्स्ट
सबसे पहले नेटवर्क से जवाब का अनुरोध करता है. अगर कोई जवाब नहीं मिलता है, तो कैश मेमोरी में जवाब देखता है.
फिर से पुष्टि करते समय पुराना हो
कैश मेमोरी से जवाब दिखाता है. साथ ही, बैकग्राउंड में एसेट के नए वर्शन का अनुरोध करता है और उसे कैश मेमोरी में सेव करता है, ताकि अगली बार एसेट का अनुरोध किए जाने पर उसे तुरंत दिखाया जा सके.
सिर्फ़ नेटवर्क
नेटवर्क से मिले जवाब या गड़बड़ियों के बारे में हमेशा जवाब देता है. कैश मेमोरी का कभी इस्तेमाल नहीं किया जाता.
सिर्फ़ कैश मेमोरी
हमेशा कैश मेमोरी से जवाब देता है या गड़बड़ियों की जानकारी देता है. नेटवर्क से कभी भी संपर्क नहीं किया जाएगा. इस रणनीति का इस्तेमाल करके दिखाई जाने वाली एसेट को अनुरोध करने से पहले, कैश मेमोरी में जोड़ना ज़रूरी है.

पहले कैश मेमोरी में सेव करना

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

कैश मेमोरी में डेटा सेव करने की रणनीति

self.addEventListener("fetch", event => {
   event.respondWith(
     caches.match(event.request)
     .then(cachedResponse => {
       // It can update the cache to serve updated content on the next request
         return cachedResponse || fetch(event.request);
     }
   )
  )
});

नेटवर्क पहले

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

नेटवर्क फ़र्स्ट रणनीति

self.addEventListener("fetch", event => {
   event.respondWith(
     fetch(event.request)
     .catch(error => {
       return caches.match(event.request) ;
     })
   );
});

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

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

फिर से पुष्टि करने की रणनीति के दौरान पुराना हो गया

self.addEventListener('fetch', event => {
  event.respondWith(
    caches.match(event.request).then(cachedResponse => {
        const networkFetch = fetch(event.request).then(response => {
          // update the cache with a clone of the network response
          const responseClone = response.clone()
          caches.open(url.searchParams.get('name')).then(cache => {
            cache.put(event.request, responseClone)
          })
          return response
        }).catch(function (reason) {
          console.error('ServiceWorker fetch failed: ', reason)
        })
        // prioritize cached response over network
        return cachedResponse || networkFetch
      }
    )
  )
})

सिर्फ़ नेटवर्क

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

सिर्फ़ नेटवर्क की रणनीति

सिर्फ़ कैश मेमोरी

सिर्फ़ कैश मेमोरी का इस्तेमाल करने की रणनीति से यह पक्का होता है कि अनुरोध कभी भी नेटवर्क पर न जाएं. आने वाले सभी अनुरोधों का जवाब, पहले से भरे हुए कैश आइटम से दिया जाता है. यहां दिया गया कोड, सिर्फ़ कैश मेमोरी का जवाब देने के लिए, कैश मेमोरी के match तरीके के साथ fetch इवेंट हैंडलर का इस्तेमाल करता है:

self.addEventListener("fetch", event => {
   event.respondWith(caches.match(event.request));
});

सिर्फ़ कैश मेमोरी का इस्तेमाल करने की रणनीति.

कस्टम रणनीतियां

ऊपर दी गई कैश मेमोरी सेव करने की सामान्य रणनीतियां हैं. हालांकि, आपके पास अपने सर्विस वर्कर और अनुरोधों को मैनेज करने का विकल्प होता है. अगर इनमें से कोई भी विकल्प आपकी ज़रूरतों के मुताबिक नहीं है, तो अपना विकल्प बनाएं.

उदाहरण के लिए, अपडेट किए गए कॉन्टेंट को प्राथमिकता देने के लिए, टाइम आउट के साथ नेटवर्क फ़र्स्ट की रणनीति का इस्तेमाल किया जा सकता है. हालांकि, ऐसा सिर्फ़ तब किया जा सकता है, जब जवाब आपके सेट किए गए थ्रेशोल्ड में दिखे. कैश मेमोरी में सेव किए गए रिस्पॉन्स को नेटवर्क रिस्पॉन्स के साथ मर्ज किया जा सकता है. साथ ही, सेवा वर्कर से जटिल रिस्पॉन्स भी बनाया जा सकता है.

ऐसेट अपडेट करना

अपने PWA की कैश मेमोरी में सेव की गई ऐसेट को अप-टू-डेट रखना मुश्किल हो सकता है. ऐसा करने का एक तरीका, फिर से पुष्टि करते समय पुराने डेटा का इस्तेमाल करना है. हालांकि, इसके अलावा और भी तरीके हैं. अपडेट वाले चैप्टर में, आपको अपने ऐप्लिकेशन के कॉन्टेंट और एसेट को अपडेट रखने के लिए अलग-अलग तरीके जानने को मिलेंगे.

संसाधन