एक सर्विस वर्कर की ज़िंदगी

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

Workbox का इस्तेमाल करने से पहले, सेवा वर्कर के लाइफ़साइकल को समझना ज़रूरी है, ताकि आपको यह पता चल सके कि Workbox क्या करता है.

शर्तें तय करना

सर्विस वर्कर्स के लाइफ़साइकल के बारे में जानने से पहले, इस लाइफ़साइकल के काम करने के तरीके के बारे में कुछ शब्दों की जानकारी देना ज़रूरी है.

कंट्रोल और स्कोप

सेवा वर्कर्स के काम करने के तरीके को समझने के लिए, कंट्रोल का कॉन्सेप्ट जानना ज़रूरी है. जिस पेज को सर्विस वर्कर से कंट्रोल किया जा रहा है वह ऐसा पेज होता है जो सर्विस वर्कर को उसकी ओर से नेटवर्क अनुरोधों को इंटरसेप्ट करने की अनुमति देता है. सर्विस वर्कर मौजूद है और वह दिए गए दायरे में पेज के लिए काम कर सकता है.

दायरा

किसी सेवा वर्कर का दायरा, वेब सर्वर पर उसकी जगह से तय होता है. अगर कोई सर्विस वर्कर /subdir/index.html पर मौजूद पेज पर चलता है और वह /subdir/sw.js पर मौजूद है, तो सर्विस वर्कर का दायरा /subdir/ है. दायरे के कॉन्सेप्ट को काम करते हुए देखने के लिए, यह उदाहरण देखें:

  1. https://service-worker-scope-viewer.glitch.me/subdir/index.html पर जाएं. आपको एक मैसेज दिखेगा, जिसमें बताया जाएगा कि कोई भी सर्विस वर्कर, पेज को कंट्रोल नहीं कर रहा है. हालांकि, वह पेज https://service-worker-scope-viewer.glitch.me/subdir/sw.js से एक सर्विस वर्कर रजिस्टर करता है.
  2. पेज को फिर से लोड करें. सर्विस वर्कर रजिस्टर हो गया है और अब चालू है, इसलिए वह पेज को कंट्रोल कर रहा है. आपको एक फ़ॉर्म दिखेगा, जिसमें सेवा वर्कर का दायरा, मौजूदा स्थिति, और उसका यूआरएल शामिल होगा. ध्यान दें: पेज को रीफ़्रेश करने का दायरे से कोई लेना-देना नहीं है. इसके बजाय, यह सर्विस वर्कर के लाइफ़साइकल से जुड़ा है. इस बारे में बाद में बताया जाएगा.
  3. अब https://service-worker-scope-viewer.glitch.me/index.html पर जाएं. इस ऑरिजिन पर एक सर्विस वर्कर रजिस्टर किया गया था, फिर भी यह मैसेज दिखता है कि कोई मौजूदा सर्विस वर्कर नहीं है. ऐसा इसलिए होता है, क्योंकि यह पेज रजिस्टर किए गए सर्विस वर्कर के दायरे में नहीं आता.

स्कोप से यह तय होता है कि सर्विस वर्कर किन पेजों को कंट्रोल करता है. इस उदाहरण में, इसका मतलब है कि /subdir/sw.js से लोड किया गया सर्विस वर्कर, सिर्फ़ /subdir/ या उसके सबट्री में मौजूद पेजों को कंट्रोल कर सकता है.

ऊपर बताया गया तरीका, स्कोपिंग की डिफ़ॉल्ट सेटिंग है. हालांकि, ज़्यादा से ज़्यादा स्कोप को बदला जा सकता है. इसके लिए, Service-Worker-Allowed रिस्पॉन्स हेडर सेट करें. साथ ही, register तरीके में scope विकल्प पास करें.

जब तक किसी ऑरिजिन के सबसेट तक सर्विस वर्कर के दायरे को सीमित करने की कोई बहुत अच्छी वजह न हो, तब तक वेब सर्वर की रूट डायरेक्ट्री से सर्विस वर्कर लोड करें, ताकि उसका दायरा ज़्यादा से ज़्यादा हो. साथ ही, Service-Worker-Allowed हेडर के बारे में चिंता न करें. ऐसा करने पर, सभी के लिए यह काफ़ी आसान हो जाता है.

क्लाइंट

जब यह कहा जाता है कि कोई सर्विस वर्कर किसी पेज को कंट्रोल कर रहा है, तो इसका मतलब है कि वह असल में किसी क्लाइंट को कंट्रोल कर रहा है. क्लाइंट वह खुला पेज होता है जिसका यूआरएल उस सेवा वर्कर के दायरे में आता है. खास तौर पर, ये WindowClient के उदाहरण हैं.

नए सेवा वर्कर की लाइफ़साइकल

किसी पेज को कंट्रोल करने के लिए, सेवा वर्कर को पहले चालू करना होगा. आइए, इस बात से शुरुआत करते हैं कि किसी ऐसी वेबसाइट के लिए नया सेवा वर्कर डिप्लॉय करने पर क्या होता है जिसमें कोई सेवा वर्कर चालू नहीं है.

रजिस्ट्रेशन

रजिस्ट्रेशन, सर्विस वर्कर के लाइफ़साइकल का पहला चरण है:

<!-- In index.html, for example: -->
<script>
  // Don't register the service worker
  // until the page has fully loaded
  window.addEventListener('load', () => {
    // Is service worker available?
    if ('serviceWorker' in navigator) {
      navigator.serviceWorker.register('/sw.js').then(() => {
        console.log('Service worker registered!');
      }).catch((error) => {
        console.warn('Error registering service worker:');
        console.warn(error);
      });
    }
  });
</script>

यह कोड मुख्य थ्रेड पर चलता है और ये काम करता है:

  1. उपयोगकर्ता पहली बार किसी वेबसाइट पर, रजिस्टर किए गए सेवा वर्कर के बिना पहुंचता है. इसलिए, किसी सेवा वर्कर को रजिस्टर करने से पहले, तब तक इंतज़ार करें, जब तक पेज पूरी तरह से लोड न हो जाए. इससे, अगर सेवा वर्कर पहले से कुछ कैश मेमोरी में सेव कर लेता है, तो बैंडविड्थ का इस्तेमाल कम होता है.
  2. सर्विस वर्कर की सुविधा का इस्तेमाल करने में कोई समस्या नहीं होती. हालांकि, एक बार जांच करने से उन ब्राउज़र में गड़बड़ियों से बचा जा सकता है जिनमें यह सुविधा काम नहीं करती.
  3. जब पेज पूरी तरह लोड हो जाए और सर्विस वर्कर काम करता हो, तो /sw.js को रजिस्टर करें.

इन बातों को समझना ज़रूरी है:

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

रजिस्ट्रेशन पूरा होने के बाद, इंस्टॉलेशन शुरू हो जाता है.

इंस्टॉल करना

रजिस्ट्रेशन के बाद, सेवा वर्कर अपना install इवेंट ट्रिगर करता है. हर सेवा वर्कर के लिए, install को सिर्फ़ एक बार कॉल किया जाता है. यह तब तक फिर से ट्रिगर नहीं होगा, जब तक इसे अपडेट नहीं किया जाता. install इवेंट के लिए, addEventListener की मदद से वर्कर्स के स्कोप में कॉलबैक रजिस्टर किया जा सकता है:

// /sw.js
self.addEventListener('install', (event) => {
  const cacheKey = 'MyFancyCacheName_v1';

  event.waitUntil(caches.open(cacheKey).then((cache) => {
    // Add all the assets in the array to the 'MyFancyCacheName_v1'
    // `Cache` instance for later use.
    return cache.addAll([
      '/css/global.bc7b80b7.css',
      '/css/home.fe5d0b23.css',
      '/js/home.d3cc4ba4.js',
      '/js/jquery.43ca4933.js'
    ]);
  }));
});

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

  1. 'MyFancyCache_v1' नाम का नया Cache इंस्टेंस बनाता है.
  2. कैश मेमोरी बनने के बाद, ऐसेट यूआरएल के कलेक्शन को एसिंक्रोनस addAll तरीके का इस्तेमाल करके पहले से कैश मेमोरी में सेव कर लिया जाता है.

अगर event.waitUntil को दिए गए वादे अस्वीकार कर दिए जाते हैं, तो इंस्टॉलेशन पूरा नहीं होता. ऐसा होने पर, सेवा वर्कर को खारिज कर दिया जाता है.

अगर वादे पूरे हो जाते हैं, तो इंस्टॉलेशन पूरा हो जाता है और सेवा वर्कर की स्थिति 'installed' में बदल जाती है. इसके बाद, वह चालू हो जाता है.

ऐक्टिवेशन से जुड़ी सेटिंग

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

नए सेवा वर्कर के लिए, install के पूरा होने के तुरंत बाद activate ट्रिगर होता है. चालू होने के बाद, सेवा वर्कर का स्टेटस 'activated' हो जाता है. ध्यान दें कि डिफ़ॉल्ट रूप से, अगले नेविगेशन या पेज के रीफ़्रेश होने तक, नया सर्विस वर्कर पेज को कंट्रोल नहीं करेगा.

सेवा वर्कर के अपडेट मैनेज करना

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

अपडेट कब होते हैं

ब्राउज़र, सेवा वर्कर के अपडेट की जांच तब करेंगे, जब:

  • उपयोगकर्ता, सर्विस वर्कर के दायरे में मौजूद किसी पेज पर जाता है.
  • navigator.serviceWorker.register() को, फ़िलहाल इंस्टॉल किए गए सर्विस वर्कर से अलग यूआरएल के साथ कॉल किया जाता है—हालांकि, सर्विस वर्कर के यूआरएल में बदलाव न करें!
  • navigator.serviceWorker.register() को, इंस्टॉल किए गए सेवा वर्कर के यूआरएल के साथ, लेकिन अलग दायरे में कॉल किया जाता है. अगर हो सके, तो स्कोप को किसी ऑरिजिन के रूट पर रखकर, इस समस्या से बचें.
  • जब 'push' या 'sync' जैसे इवेंट, पिछले 24 घंटों में ट्रिगर हुए हों—हालांकि, अभी इन इवेंट के बारे में चिंता न करें.

अपडेट कैसे होते हैं

यह जानना ज़रूरी है कि ब्राउज़र, सेवा वर्कर को कब अपडेट करता है. हालांकि, यह जानना भी ज़रूरी है कि वह "कैसे" अपडेट करता है. अगर किसी सेवा वर्कर के यूआरएल या दायरे में कोई बदलाव नहीं हुआ है, तो मौजूदा सेवा वर्कर सिर्फ़ तब नए वर्शन में अपडेट होता है, जब उसके कॉन्टेंट में बदलाव हुआ हो.

ब्राउज़र, बदलावों का पता कई तरीकों से लगाते हैं:

  • अगर लागू हो, तो importScripts के अनुरोध पर, स्क्रिप्ट में बाइट-बाय-बाइट किए गए बदलाव.
  • सेवा वर्कर के टॉप-लेवल कोड में किया गया कोई भी बदलाव, जिससे ब्राउज़र के जनरेट किए गए फ़िंगरप्रिंट पर असर पड़ता है.

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

अपडेट की जांच को मैन्युअल तरीके से ट्रिगर करना

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

navigator.serviceWorker.ready.then((registration) => {
  registration.update();
});

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

इंस्टॉल करना

स्टैटिक ऐसेट जनरेट करने के लिए बंडलर का इस्तेमाल करने पर, उन ऐसेट के नाम में हैश शामिल होंगे. जैसे, framework.3defa9d2.js. मान लें कि उनमें से कुछ ऐसेट को बाद में ऑफ़लाइन ऐक्सेस करने के लिए पहले से कैश मेमोरी में सेव किया गया है. अपडेट की गई एसेट को पहले से कैश मेमोरी में सेव करने के लिए, सेवा वर्कर को अपडेट करना होगा:

self.addEventListener('install', (event) => {
  const cacheKey = 'MyFancyCacheName_v2';

  event.waitUntil(caches.open(cacheKey).then((cache) => {
    // Add all the assets in the array to the 'MyFancyCacheName_v2'
    // `Cache` instance for later use.
    return cache.addAll([
      '/css/global.ced4aef2.css',
      '/css/home.cbe409ad.css',
      '/js/home.109defa4.js',
      '/js/jquery.38caf32d.js'
    ]);
  }));
});

पहले दिए गए install इवेंट के उदाहरण से, इस इवेंट में दो चीज़ें अलग हैं:

  1. 'MyFancyCacheName_v2' की के साथ एक नया Cache इंस्टेंस बनाया जाता है.
  2. पहले से कैश मेमोरी में सेव की गई एसेट के नाम बदल गए हैं.

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

जब पुराने सेवा वर्कर से कोई क्लाइंट कंट्रोल नहीं किया जा रहा होगा, तब डिफ़ॉल्ट रूप से नया सेवा वर्कर चालू हो जाएगा. ऐसा तब होता है, जब उस वेबसाइट के सभी खुले हुए टैब बंद कर दिए जाते हैं.

ऐक्टिवेशन से जुड़ी सेटिंग

अपडेट किया गया सर्विस वर्कर इंस्टॉल होने और इंतज़ार का समय खत्म होने के बाद, वह चालू हो जाता है और पुराने सर्विस वर्कर को हटा दिया जाता है. अपडेट किए गए सर्विस वर्कर के activate इवेंट में, पुराने कैश मेमोरी को हटाना एक सामान्य काम है. caches.keys की मदद से, सभी खुले Cache इंस्टेंस के लिए कुंजियां पाकर और caches.delete की मदद से, अनुमति वाली सूची में शामिल नहीं किए गए कैश मेमोरी को मिटाकर, पुराने कैश मेमोरी हटाएं:

self.addEventListener('activate', (event) => {
  // Specify allowed cache keys
  const cacheAllowList = ['MyFancyCacheName_v2'];

  // Get all the currently active `Cache` instances.
  event.waitUntil(caches.keys().then((keys) => {
    // Delete all caches that aren't in the allow list:
    return Promise.all(keys.map((key) => {
      if (!cacheAllowList.includes(key)) {
        return caches.delete(key);
      }
    }));
  }));
});

पुराने कैश मेमोरी अपने-आप नहीं मिटते. हमें यह काम खुद करना होगा. ऐसा न करने पर, स्टोरेज कोटा की सीमा पार हो सकती है. पहले सेवा वर्कर का 'MyFancyCacheName_v1' पुराना हो गया है. इसलिए, कैश मेमोरी में सेव करने की अनुमति वाली सूची को अपडेट करके 'MyFancyCacheName_v2' सेट किया गया है. यह सूची, कैश मेमोरी में सेव किए गए ऐसे कॉन्टेंट को मिटा देती है जिसका नाम अलग है.

पुराना कैश मेमोरी हटाने के बाद, activate इवेंट पूरा हो जाएगा. इस समय, नया सर्विस वर्कर पेज को कंट्रोल करेगा और आखिर में पुराने सर्विस वर्कर की जगह ले लेगा!

लाइफ़साइकल कभी खत्म नहीं होता

भले ही, सेवा वर्कर को डिप्लॉय करने और अपडेट करने के लिए, Workbox का इस्तेमाल किया जा रहा हो या सीधे तौर पर सेवा वर्कर एपीआई का इस्तेमाल किया जा रहा हो, फिर भी सेवा वर्कर के लाइफ़साइकल को समझना ज़रूरी है. इस जानकारी के आधार पर, आपको सेवा वर्कर के व्यवहारों को समझने में आसानी होगी.

अगर आपको इस विषय के बारे में ज़्यादा जानना है, तो जेक आर्किबाल्ड का यह लेख पढ़ें. सेवा के लाइफ़साइकल के बारे में बहुत कुछ जानना ज़रूरी है, लेकिन इसे जानना ज़रूरी है. यह जानकारी, Workbox का इस्तेमाल करते समय बहुत काम आएगी.