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

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

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

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

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

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

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

स्कोप

सर्विस वर्कर के दायरे को वेब सर्वर पर उसकी जगह से तय किया जाता है. अगर कोई सर्विस वर्कर, /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 रजिस्टर करें.

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

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

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