Bulletin की टीम को PWA बनाते समय, सेवा वर्कर के बारे में क्या पता चला.
यह ब्लॉग पोस्ट, एक सीरीज़ की पहली पोस्ट है. इसमें, Google Bulletin की टीम को बाहरी लोगों के लिए PWA बनाते समय मिले अनुभवों के बारे में बताया गया है. इन पोस्ट में, हम आपको उन चुनौतियों के बारे में बताएंगे जिनका सामना हमें करना पड़ा. साथ ही, उनसे निपटने के तरीकों और आम तौर पर होने वाली गलतियों से बचने के बारे में सलाह भी देंगे. यह किसी भी तरह से, PWA के बारे में पूरी जानकारी नहीं है. इसका मकसद, हमारी टीम के अनुभव से मिली सीखों को शेयर करना है.
इस पहली पोस्ट में, हम आपको इस बारे में थोड़ी जानकारी देंगे कि सेवा वर्कर क्या हैं. इसके बाद, हम सेवा वर्कर के बारे में अपनी सभी जानकारी शेयर करेंगे.
बैकग्राउंड
बुलेटिन को साल 2017 के मध्य से 2019 के मध्य तक डेवलप किया गया था.
हमने PWA बनाने का विकल्प क्यों चुना
डेवलपमेंट की प्रोसेस के बारे में जानने से पहले, यह देखें कि इस प्रोजेक्ट के लिए PWA बनाना क्यों एक बेहतर विकल्प था:
- तुरंत दोहराए जाने की सुविधा. यह जानकारी खास तौर पर अहम है, क्योंकि Bulletin को कई बाज़ारों में पायलट किया जाएगा.
- सिंगल कोड बेस. हमारे उपयोगकर्ताओं को Android और iOS के बीच लगभग बराबर-बराबर बांटा गया था. PWA का मतलब है कि हम एक ऐसा वेब ऐप्लिकेशन बना सकते हैं जो दोनों प्लैटफ़ॉर्म पर काम करेगा. इससे टीम की परफ़ॉर्मेंस और असर बेहतर हुआ.
- इन्हें तुरंत अपडेट किया जाता है और ये उपयोगकर्ता के व्यवहार पर निर्भर नहीं होते. PWA अपने-आप अपडेट हो सकते हैं. इससे, डिवाइसों पर इस्तेमाल किए जा रहे पुराने क्लाइंट की संख्या कम हो जाती है. हमने क्लाइंट के लिए, माइग्रेशन में लगने वाले समय को कम करके, बैकएंड में बड़े बदलाव किए.
- पहले और तीसरे पक्ष के ऐप्लिकेशन के साथ आसानी से इंटिग्रेट किया जा सकता है. ऐप्लिकेशन के लिए, ऐसे इंटिग्रेशन ज़रूरी थे. पीडब्ल्यूए के साथ, इसका मतलब अक्सर सिर्फ़ यूआरएल खोलना होता था.
- ऐप्लिकेशन इंस्टॉल करने में आने वाली समस्याओं को दूर किया.
हमारा फ़्रेमवर्क
हमने बुलेटिन के लिए Polymer का इस्तेमाल किया है. हालांकि, कोई भी आधुनिक और अच्छी तरह से काम करने वाला फ़्रेमवर्क इस्तेमाल किया जा सकता है.
हमने सर्विस वर्कर के बारे में क्या सीखा
सर्विस वर्कर के बिना, कोई PWA नहीं बनाया जा सकता. सर्विस वर्कर से आपको बहुत ज़्यादा पावर मिलती है, जैसे कि बेहतर कैश मेमोरी, ऑफ़लाइन काम करने की सुविधाएं, बैकग्राउंड सिंक वगैरह. वैसे तो, सर्विस वर्कर थोड़ी मुश्किलें पैदा करते हैं, लेकिन हमने पाया कि इससे मिलने वाले फ़ायदे, ज़्यादा मुश्किलों से ज़्यादा मुश्किल हो जाते हैं.
अगर हो सके, तो इसे जनरेट करें
सर्विस वर्कर स्क्रिप्ट को मैन्युअल तरीके से लिखने से बचें. सर्विस वर्कर को मैन्युअल तरीके से लिखने के लिए, कैश मेमोरी में सेव किए गए संसाधनों को मैन्युअल तरीके से मैनेज करना पड़ता है. साथ ही, Workbox जैसी ज़्यादातर सर्विस वर्कर लाइब्रेरी के लिए, लॉजिक को फिर से लिखना पड़ता है.
हालांकि, हमारे इंटरनल टेक्नोलॉजी स्टैक की वजह से हम अपना सर्विस वर्कर जनरेट और मैनेज करने के लिए, लाइब्रेरी का इस्तेमाल नहीं कर सके. नीचे दी गई जानकारी से यह पता चलता है. ज़्यादा पढ़ने के लिए, जनरेट नहीं किए गए सर्विस वर्कर के लिए होने वाले नुकसान पर जाएं.
सभी लाइब्रेरी, सेवा-कर्मी के साथ काम नहीं करतीं
कुछ JS लाइब्रेरी ऐसी गलतियां करती हैं जो सेवा वर्कर के ज़रिए चलाए जाने पर उम्मीद के मुताबिक काम नहीं करती हैं. उदाहरण के लिए, window
या document
के उपलब्ध होने का अनुमान लगाना या ऐसे एपीआई का इस्तेमाल करना जो सेवा करने वाले लोगों (XMLHttpRequest
, लोकल स्टोरेज वगैरह) के लिए उपलब्ध नहीं है. पक्का करें कि आपके ऐप्लिकेशन के लिए ज़रूरी लाइब्रेरी, सेवा-कर्मी के साथ काम करती हों. इस खास PWA के लिए, हम पुष्टि करने के लिए gapi.js का इस्तेमाल करना चाहते थे. हालांकि, ऐसा नहीं हो सका, क्योंकि यह सर्विस वर्कर के साथ काम नहीं करता. लाइब्रेरी के लेखकों को, जहां भी हो सके वहां JavaScript कॉन्टेक्स्ट के बारे में ग़ैर-ज़रूरी अनुमान कम करने या हटाने चाहिए, ताकि सेवा वर्कर के इस्तेमाल के उदाहरणों को बेहतर तरीके से दिखाया जा सके. जैसे, सेवा वर्कर के साथ काम न करने वाले एपीआई का इस्तेमाल न करना और ग्लोबल स्टेटस का इस्तेमाल न करना.
शुरू करने के दौरान IndexedDB को ऐक्सेस करने से बचें
अपनी सेवा वर्कर स्क्रिप्ट को शुरू करते समय, IndexedDB को न पढ़ें. ऐसा न करने पर, आपको यह गड़बड़ी दिख सकती है:
- उपयोगकर्ता के पास IndexedDB (IDB) के वर्शन N वाला वेब ऐप्लिकेशन है
- नया वेब ऐप्लिकेशन, IDB के N+1 वर्शन के साथ पुश किया जाता है
- उपयोगकर्ता PWA पर जाता है, जिससे नए सेवा वर्कर को डाउनलोड करने की प्रोसेस शुरू होती है
- नया सर्विस वर्कर,
install
इवेंट हैंडलर को रजिस्टर करने से पहले IDB से पढ़ता है, जिससे N से N+1 पर जाने के लिए IDB अपग्रेड साइकल ट्रिगर होता है - उपयोगकर्ता के पास N वर्शन वाला पुराना क्लाइंट है. इसलिए, सेवा वर्कर को अपग्रेड करने की प्रोसेस रुक जाती है, क्योंकि डेटाबेस के पुराने वर्शन के लिए अब भी चालू कनेक्शन मौजूद हैं
- सर्विस वर्कर हैंग हो जाता है और कभी इंस्टॉल नहीं होता
हमारे मामले में, सेवा वर्कर के इंस्टॉल होने पर कैश मेमोरी अमान्य हो गई थी. इसलिए, अगर सेवा वर्कर कभी इंस्टॉल नहीं हुआ, तो उपयोगकर्ताओं को अपडेट किया गया ऐप्लिकेशन कभी नहीं मिला.
इसे लचीला बनाएं
हालांकि, सेवा वर्कर स्क्रिप्ट बैकग्राउंड में चलती हैं, लेकिन इन्हें किसी भी समय बंद किया जा सकता है. भले ही, वे I/O ऑपरेशन (नेटवर्क, आईडीबी वगैरह) के बीच में हों. लंबे समय तक चलने वाली किसी भी प्रोसेस को किसी भी समय फिर से शुरू किया जा सकता है.
सिंक करने की उस प्रोसेस के मामले में जिसमें बड़ी फ़ाइलों को सर्वर पर अपलोड किया गया और IDB में सेव किया गया, अपलोड के बीच में रुकने की समस्या को हल करने के लिए, हमने अपनी इंटरनल अपलोड लाइब्रेरी के फिर से शुरू किए जा सकने वाले सिस्टम का फ़ायदा लिया. इसके लिए, हमने अपलोड करने से पहले, फिर से शुरू किए जा सकने वाले अपलोड के यूआरएल को IDB में सेव किया. साथ ही, अगर अपलोड पहली बार पूरा नहीं हुआ, तो उस यूआरएल का इस्तेमाल करके अपलोड फिर से शुरू किया. साथ ही, लंबे समय तक चलने वाले किसी भी I/O ऑपरेशन से पहले, स्थिति को आईडीबी में सेव किया जाता था, ताकि यह पता चल सके कि हम हर रिकॉर्ड के लिए प्रोसेस में कहां थे.
ग्लोबल स्टेटस पर निर्भर न रहें
सर्विस वर्कर किसी अलग संदर्भ में मौजूद होते हैं. इसलिए, हो सकता है कि आपको कई ऐसे सिंबल न दिखें जिनकी उम्मीद हो. हमारे बहुत सारे कोड window
कॉन्टेक्स्ट के साथ-साथ सर्विस वर्कर के कॉन्टेक्स्ट में भी चले. जैसे- लॉगिंग, फ़्लैग, सिंकिंग वगैरह. कोड को उन सेवाओं के लिए सुरक्षात्मक होना चाहिए जिनका इस्तेमाल किया जाता है, जैसे कि लोकल स्टोरेज या कुकी. ग्लोबल ऑब्जेक्ट को ऐसे रेफ़र करने के लिए, globalThis
का इस्तेमाल किया जा सकता है जिससे यह सभी संदर्भों में काम करे. ग्लोबल वैरिएबल में सेव किए गए डेटा का भी कम इस्तेमाल करें. इसकी कोई गारंटी नहीं है कि स्क्रिप्ट कब बंद हो जाएगी और स्क्रीन की स्थिति कब हट जाएगी.
लोकल डेवलपमेंट
सेवा वर्कर का एक मुख्य कॉम्पोनेंट, स्थानीय तौर पर संसाधनों को कैश मेमोरी में सेव करना है. हालांकि, डेवलपमेंट के दौरान यह आपकी उम्मीद से पूरी तरह विपरे होता है, खास तौर पर तब, जब अपडेट लेज़ी तरीके से किए गए हों. आपको अब भी सर्वर वर्कर्स को इंस्टॉल रखना है, ताकि आप उससे जुड़ी समस्याओं को डीबग कर सकें या बैकग्राउंड सिंक या सूचनाओं जैसे अन्य एपीआई के साथ काम कर सकें. Chrome पर, आप Chrome DevTools की मदद से नेटवर्क के लिए बायपास चेकबॉक्स (ऐप्लिकेशन पैनल > सर्विस वर्कर पैनल) को चालू करके भी ऐसा कर सकते हैं. इससे मेमोरी कैश को भी बंद करने के लिए नेटवर्क पैनल में कैश मेमोरी बंद करें चेकबॉक्स को चालू किया जा सकता है. ज़्यादा ब्राउज़र को कवर करने के लिए, हमने एक अलग समाधान चुना है. इसके लिए, हमने अपने सेवा वर्कर में कैश मेमोरी का इस्तेमाल बंद करने के लिए एक फ़्लैग जोड़ा है. यह फ़्लैग, डेवलपर के बिल्ड में डिफ़ॉल्ट रूप से चालू होता है. इससे यह पक्का होता है कि डेवलपर को कैश मेमोरी में सेव होने की प्रोसेस से जुड़ी किसी भी समस्या के बिना, हमेशा अपने सबसे नए बदलाव मिलते रहें. ब्राउज़र को किसी भी ऐसेट को कैश मेमोरी में सेव होने से रोकने के लिए, Cache-Control: no-cache
हेडर को शामिल करना ज़रूरी है.
लाइटहाउस
Lighthouse, पीडब्ल्यूए के लिए डीबग करने वाले कई काम के टूल उपलब्ध कराता है. यह टूल किसी साइट को स्कैन करता है और PWA, परफ़ॉर्मेंस, ऐक्सेस करने की सुविधा, एसईओ, और अन्य सबसे सही तरीकों से जुड़ी रिपोर्ट जनरेट करता है. हमारा सुझाव है कि लाइटहाउस को लगातार इंटिग्रेशन पर चलाएं, ताकि अगर आपने PWA बनने की किसी शर्त को पूरा नहीं किया, तो आपको इसकी सूचना मिल सके. हमारे साथ एक बार ऐसा हुआ था, जहां सर्विस वर्कर इंस्टॉल नहीं कर रहा था और प्रोडक्शन शुरू होने से पहले हमें इसके बारे में पता नहीं चला था. अगर लाइटहाउस को सीआई के हिस्से के तौर पर शामिल किया गया होता, तो ऐसा नहीं होता.
लगातार डिलीवरी की सुविधा का इस्तेमाल करना
सेवा वर्कर अपने-आप अपडेट हो सकते हैं. इसलिए, उपयोगकर्ताओं के पास अपग्रेड को सीमित करने का विकल्प नहीं होता. इससे, काम न करने वाले क्लाइंट की संख्या काफ़ी कम हो जाती है. जब उपयोगकर्ता ने हमारा ऐप्लिकेशन खोला, तो सेवा वर्कर ने पुराने क्लाइंट को दिखाया. साथ ही, नए क्लाइंट को धीरे-धीरे डाउनलोड किया. नया क्लाइंट डाउनलोड होने के बाद, उपयोगकर्ता को नई सुविधाओं को ऐक्सेस करने के लिए, पेज को रीफ़्रेश करने के लिए कहा जाएगा. भले ही, उपयोगकर्ता ने इस अनुरोध को अनदेखा किया हो, लेकिन अगली बार पेज रीफ़्रेश करने पर, उसे क्लाइंट का नया वर्शन मिलेगा. इस वजह से, उपयोगकर्ता के लिए iOS/Android ऐप्लिकेशन की तरह ही, अपडेट को अस्वीकार करना मुश्किल होता है.
हमने क्लाइंट के लिए, माइग्रेशन में लगने वाले समय को कम करके, बैकएंड में बड़े बदलाव किए. आम तौर पर, हम उपयोगकर्ताओं को एक महीना देते हैं, ताकि वे बड़े बदलाव होने से पहले, नए क्लाइंट पर अपडेट कर सकें. हालांकि, ऐप्लिकेशन पुराना होने के बावजूद काम करेगा, इसलिए अगर उपयोगकर्ता ने लंबे समय तक ऐप्लिकेशन नहीं खोला होगा, तो पुराने क्लाइंट के लिए जंगल में बने रहना मुमकिन था. iOS पर, सेवा वर्कर को कुछ हफ़्तों के बाद हटा दिया जाता है, ताकि ऐसा न हो. Android के लिए, कॉन्टेंट पुराना होने के दौरान विज्ञापन न दिखाकर या कुछ हफ़्तों के बाद मैन्युअल तरीके से उसकी समयसीमा खत्म करके, इस समस्या को कम किया जा सकता है. असल में, हमें पुराने क्लाइंट से कभी कोई समस्या नहीं आई. कोई टीम इस मामले में कितनी सख्त है, यह उसके इस्तेमाल के उदाहरण पर निर्भर करता है. हालांकि, PWA, iOS/Android ऐप्लिकेशन के मुकाबले ज़्यादा सुविधाएं देते हैं.
सेवा वर्कर में कुकी की वैल्यू पाना
कभी-कभी, सेवा वर्कर के संदर्भ में कुकी वैल्यू को ऐक्सेस करना ज़रूरी होता है. हमारे मामले में, हमें पहले पक्ष के एपीआई अनुरोधों की पुष्टि करने के लिए टोकन जनरेट करना था. इसके लिए, हमें कुकी वैल्यू ऐक्सेस करनी पड़ी. सर्विस वर्कर में, document.cookies
जैसे सिंक्रोनस एपीआई उपलब्ध नहीं हैं. कुकी वैल्यू का अनुरोध करने के लिए, सर्विस वर्कर के ऐक्टिव (विंडो वाले) क्लाइंट को हमेशा मैसेज भेजा जा सकता है. हालांकि, सर्विस वर्कर के लिए विंडो क्लाइंट के बिना बैकग्राउंड में चल सकता है, जैसे कि बैकग्राउंड सिंक के दौरान. इस समस्या को हल करने के लिए, हमने अपने फ़्रंटएंड सर्वर पर एक एंडपॉइंट बनाया, जो क्लाइंट को कुकी वैल्यू को वापस भेजता है. सेवा वर्कर ने इस एंडपॉइंट पर नेटवर्क अनुरोध किया और कुकी वैल्यू पाने के लिए जवाब पढ़ा.
Cookie Store API के रिलीज़ होने के बाद, इस तरीके का इस्तेमाल करने की ज़रूरत नहीं होगी. ऐसा इसलिए, क्योंकि यह ब्राउज़र कुकी को असाइनोक्रोनस तरीके से ऐक्सेस करता है और इसका इस्तेमाल सीधे तौर पर सेवा वर्कर कर सकता है.
जनरेट नहीं किए गए सर्विस वर्कर से जुड़ी समस्याएं
पक्का करें कि कैश मेमोरी में सेव की गई किसी भी स्टैटिक फ़ाइल में बदलाव होने पर, सेवा वर्कर स्क्रिप्ट में भी बदलाव हो
आम तौर पर, PWA में सेवा वर्कर, install
फ़ेज़ के दौरान सभी स्टैटिक ऐप्लिकेशन फ़ाइलें इंस्टॉल करता है. इससे क्लाइंट, बाद में होने वाली सभी विज़िट के लिए, सीधे Cache Storage API कैश मेमोरी को ऐक्सेस कर पाते हैं. सेवा वर्कर सिर्फ़ तब इंस्टॉल होते हैं, जब ब्राउज़र को पता चलता है कि सेवा वर्कर स्क्रिप्ट में कोई बदलाव हुआ है. इसलिए, हमें यह पक्का करना था कि कैश मेमोरी में सेव की गई फ़ाइल में बदलाव होने पर, सेवा वर्कर स्क्रिप्ट फ़ाइल में भी कोई बदलाव हुआ हो. हमने अपनी सेवा वर्कर स्क्रिप्ट में स्टैटिक रिसॉर्स फ़ाइल सेट का हैश जोड़कर, मैन्युअल तरीके से ऐसा किया. इससे हर रिलीज़ में एक अलग सेवा वर्कर JavaScript फ़ाइल बनाई गई. Workbox जैसी सर्विस वर्कर लाइब्रेरी, इस प्रोसेस को आपके लिए ऑटोमेट करती हैं.
यूनिट टेस्टिंग
Service worker API, ग्लोबल ऑब्जेक्ट में इवेंट लिसनर जोड़कर काम करते हैं. उदाहरण के लिए:
self.addEventListener('fetch', (evt) => evt.respondWith(fetch('/foo')));
इसकी जांच करना मुश्किल हो सकता है, क्योंकि आपको इवेंट ट्रिगर और इवेंट ऑब्जेक्ट को मॉक करना होगा. इसके बाद, respondWith()
कॉलबैक के लिए इंतज़ार करना होगा और फिर नतीजे पर दावा करने से पहले, प्रॉमिस का इंतज़ार करना होगा. इसे व्यवस्थित करने का सबसे आसान तरीका यह है कि लागू करने की सभी प्रोसेस को किसी दूसरी फ़ाइल को सौंप दिया जाए. इस फ़ाइल की जांच करना आसान होता है.
import fetchHandler from './fetch_handler.js';
self.addEventListener('fetch', (evt) => evt.respondWith(fetchHandler(evt)));
सेवा वर्कर स्क्रिप्ट की यूनिट टेस्टिंग में आने वाली समस्याओं की वजह से, हमने मुख्य सेवा वर्कर स्क्रिप्ट को जितना हो सके उतना छोटा रखा है. साथ ही, ज़्यादातर लागू करने की प्रोसेस को अन्य मॉड्यूल में बांटा है. चूंकि, ये फ़ाइलें सिर्फ़ स्टैंडर्ड JS मॉड्यूल थीं, इसलिए इन्हें स्टैंडर्ड टेस्ट लाइब्रेरी की मदद से आसानी से यूनिट टेस्ट किया जा सकता था.
दूसरे और तीसरे हिस्से के लिए हमारे साथ बने रहें
इस सीरीज़ के दूसरे और तीसरे हिस्से में, हम मीडिया मैनेजमेंट और iOS से जुड़ी समस्याओं के बारे में बात करेंगे. अगर आपको Google पर PWA बनाने के बारे में ज़्यादा जानकारी चाहिए, तो लेखक की हमारी प्रोफ़ाइलों पर जाएं और हमसे संपर्क करने का तरीका जानें: