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

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

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

शब्द तय करना

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

कंट्रोल और दायरा

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

दायरा

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

कुछ ज़रूरी चीज़ों को समझना ज़रूरी है:

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

नए सर्विस वर्कर के लिए, activate, install के ऐक्टिव होने के तुरंत बाद फ़ायर हो जाता है. चालू हो जाने के बाद, सर्विस वर्कर की स्थिति '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 इवेंट में पुराने कैश में काट-छांट करना एक सामान्य टास्क है. पुरानी कैश मेमोरी हटाने के लिए, खुले हुए सभी Cache इंस्टेंस के लिए कुंजियां पाएं caches.keys उन कैश मेमोरी को मिटाना जो अनुमति वाली सूची में नहीं हैं 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 का इस्तेमाल किया जाए या नहीं, या सीधे Service Worker API का इस्तेमाल करना चाहिए, यह सर्विस वर्कर के लाइफ़साइकल को समझने में मदद करता है. इस समझ के साथ, सर्विस वर्कर का व्यवहार रहस्यमयी से ज़्यादा तार्किक होना चाहिए.

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