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

यह एक समस्या हो सकती है, क्योंकि हो सकता है कि उपयोगकर्ता के पास मौजूद असरदार इंटरनेट कनेक्शन टाइप असल में 3G, 4G या वाई-फ़ाई न हो. ऐसा हो सकता है कि आप कॉफ़ी शॉप के वाई-फ़ाई से कनेक्ट हों, लेकिन मोबाइल हॉटस्पॉट से कनेक्ट होने पर आपको 2G स्पीड मिले.
JavaScript के नेटवर्क ट्रांसफ़र की लागत को इन तरीकों से कम किया जा सकता है:
- सिर्फ़ वह कोड भेजना जिसकी उपयोगकर्ता को ज़रूरत है.
- कोड-स्प्लिटिंग का इस्तेमाल करके, अपने JavaScript को ज़रूरी और ग़ैर-ज़रूरी हिस्सों में बांटें. webpack जैसे मॉड्यूल बंडलर, कोड-स्प्लिटिंग की सुविधा देते हैं.
- ऐसे कोड को लेज़ी लोड करना जो ज़रूरी नहीं है.
- काट-छांट
- ES5 कोड को छोटा करने के लिए, UglifyJS का इस्तेमाल करें.
- ES2015+ को छोटा करने के लिए, babel-minify या uglify-es का इस्तेमाल करें.
- कंप्रेशन
- टेक्स्ट आधारित संसाधनों को कंप्रेस करने के लिए, कम से कम gzip का इस्तेमाल करें.
- Brotli ~q11 का इस्तेमाल करें. Brotli, कंप्रेशन रेशियो के मामले में gzip से बेहतर है. इससे CertSimple को कंप्रेस किए गए JS बाइट के साइज़ में 17% की बचत करने में मदद मिली. साथ ही, LinkedIn को पेज लोड होने में लगने वाले समय में 4% की बचत करने में मदद मिली.
- इस्तेमाल न होने वाले कोड हटाना.
- DevTools कोड कवरेज की मदद से, ऐसे कोड की पहचान करें जिसे हटाया जा सकता है या लेज़ी लोड किया जा सकता है.
- babel-preset-env और browserlist का इस्तेमाल करें, ताकि मॉडर्न ब्राउज़र में पहले से मौजूद सुविधाओं को ट्रांसपाइल न करना पड़े. बेहतर डेवलपर को अपने वेबपैक बंडल का ध्यान से विश्लेषण करने से, ग़ैर-ज़रूरी डिपेंडेंसी को कम करने के अवसरों की पहचान करने में मदद मिल सकती है.
- कोड हटाने के लिए, ट्री-शेकिंग, क्लोज़र कंपाइलर के बेहतर ऑप्टिमाइज़ेशन, और लाइब्रेरी ट्रिमिंग प्लग इन देखें. जैसे, lodash-babel-plugin या Moment.js जैसी लाइब्रेरी के लिए वेबपैक का ContextReplacementPlugin.
- नेटवर्क ट्रिप को कम करने के लिए, कोड को कैश मेमोरी में सेव करना.
- एचटीटीपी कैश मेमोरी का इस्तेमाल करें, ताकि यह पक्का किया जा सके कि ब्राउज़र, रिस्पॉन्स को कैश मेमोरी में सेव कर सकें. स्क्रिप्ट के लिए सबसे सही लाइफ़टाइम (max-age) तय करें और पुष्टि करने वाले टोकन (ETag) दें, ताकि बिना बदलाव वाली बाइट ट्रांसफ़र न हों.
- सर्विस वर्कर कैश मेमोरी, आपके ऐप्लिकेशन नेटवर्क को बेहतर बना सकती है. साथ ही, आपको V8 के कोड कैश जैसी सुविधाओं का ऐक्सेस तुरंत मिल सकता है.
- लंबे समय तक कैश मेमोरी में सेव रखने का तरीका इस्तेमाल करें, ताकि उन संसाधनों को फिर से फ़ेच न करना पड़े जिनमें कोई बदलाव नहीं हुआ है. अगर Webpack का इस्तेमाल किया जा रहा है, तो फ़ाइल नाम की हैशिंग देखें.
पार्स/कंपाइल करें
डाउनलोड होने के बाद, JavaScript की सबसे ज़्यादा लागतों में से एक, JS इंजन के लिए इस कोड को पार्स/कंपाइल करने में लगने वाला समय है. Chrome DevTools में, पार्स और कंपाइल करना, परफ़ॉर्मेंस पैनल में पीले रंग के "स्क्रिप्टिंग" समय का हिस्सा होता है.

बॉटम-अप और कॉल ट्री टैब में, पार्स/कंपाइल करने का सटीक समय दिखता है:
हालांकि, यह क्यों मायने रखता है?

कोड को पार्स/कंपाइल करने में ज़्यादा समय लगने से, उपयोगकर्ता को आपकी साइट के साथ इंटरैक्ट करने में काफ़ी देरी हो सकती है. जितना ज़्यादा JavaScript भेजा जाएगा, आपकी साइट के इंटरैक्टिव होने से पहले उसे पार्स और कंपाइल करने में उतना ही ज़्यादा समय लगेगा.
ब्राउज़र के लिए, JavaScript को प्रोसेस करना, उसी साइज़ की इमेज या वेब फ़ॉन्ट को प्रोसेस करने की तुलना में ज़्यादा मुश्किल होता है — टॉम डेल
JavaScript की तुलना में, एक ही साइज़ की इमेज को प्रोसेस करने में ज़्यादा खर्च आता है. हालांकि, इमेज को अब भी डिकोड करना पड़ता है! आम तौर पर, मोबाइल हार्डवेयर पर JS से पेज के इंटरैक्टिविटी पर बुरा असर पड़ने की संभावना ज़्यादा होती है.
जब हम पार्स और कंपाइल करने की प्रोसेस के धीमे होने की बात करते हैं, तो संदर्भ अहम होता है — हम यहां औसत मोबाइल फ़ोन की बात कर रहे हैं. आम तौर पर, लोगों के पास ऐसे फ़ोन हो सकते हैं जिनमें सीपीयू और जीपीयू की स्पीड कम हो, L2/L3 कैश मेमोरी न हो, और मेमोरी भी कम हो.
नेटवर्क की क्षमताएं और डिवाइस की क्षमताएं हमेशा एक जैसी नहीं होतीं. यह ज़रूरी नहीं है कि बेहतरीन Fiber कनेक्शन वाले उपयोगकर्ता के पास, अपने डिवाइस पर भेजी गई JavaScript को पार्स और उसका आकलन करने के लिए सबसे अच्छा सीपीयू हो. इसका उल्टा भी हो सकता है… खराब इंटरनेट कनेक्शन, लेकिन तेज़ सीपीयू. — क्रिस्टोफ़र बैक्सटर, LinkedIn
नीचे, हम कम और ज़्यादा क्षमता वाले हार्डवेयर पर, डिकंप्रेस की गई (सामान्य) ~1 एमबी JavaScript को पार्स करने की लागत देख सकते हैं. बाज़ार में मौजूद सबसे तेज़ फ़ोन और सामान्य फ़ोन के बीच, कोड को पार्स/कंपाइल करने में लगने वाले समय में दो से पांच गुना का अंतर होता है.
CNN.com जैसी असल दुनिया की साइट के बारे में क्या?
हाई-एंड iPhone 8 पर, CNN के JS को पार्स/कंपाइल करने में सिर्फ़ ~4 सेकंड लगते हैं. वहीं, Moto G4 जैसे सामान्य फ़ोन पर ~13 सेकंड लगते हैं. इससे इस बात पर काफ़ी असर पड़ सकता है कि कोई उपयोगकर्ता, इस साइट से कितनी जल्दी पूरी तरह से इंटरैक्ट कर सकता है.
इससे पता चलता है कि Moto G4 जैसे औसत हार्डवेयर पर टेस्टिंग करना कितना ज़रूरी है, न कि सिर्फ़ उस फ़ोन पर जो आपकी जेब में हो. कॉन्टेंट का संदर्भ मायने रखता है. हालांकि, अपने उपयोगकर्ताओं के डिवाइस और नेटवर्क की स्थितियों के हिसाब से कॉन्टेंट को ऑप्टिमाइज़ करें.
क्या हम वाकई बहुत ज़्यादा JavaScript भेज रहे हैं? शायद, हां :)
मोबाइल पर JavaScript की स्थिति का विश्लेषण करने के लिए, एचटीटीपी संग्रह (सबसे लोकप्रिय ~5 लाख साइटें) का इस्तेमाल करके, हम देख सकते हैं कि 50% साइटों को इंटरैक्टिव होने में 14 सेकंड से ज़्यादा समय लगता है. इन साइटों को JS को पार्स और कंपाइल करने में ही चार सेकंड तक लग जाते हैं.

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

अगर स्क्रिप्ट को लागू होने में 50 मि॰से॰ से ज़्यादा समय लगता है, तो टाइम-टू-इंटरैक्टिव में देरी होती है. यह देरी, जेएस को डाउनलोड, कंपाइल, और लागू करने में लगने वाले पूरे समय के बराबर होती है — एलेक्स रसेल
इस समस्या को हल करने के लिए, JavaScript को छोटे-छोटे हिस्सों में बांटने से फ़ायदा मिलता है. इससे मुख्य थ्रेड को लॉक होने से बचाया जा सकता है. देखें कि क्या एक्ज़ीक्यूशन के दौरान किए जा रहे काम को कम किया जा सकता है.
अन्य लागत
JavaScript, पेज की परफ़ॉर्मेंस पर अन्य तरीकों से भी असर डाल सकता है:
- मेमोरी. जीसी (गारबेज कलेक्शन) की वजह से, पेज बार-बार रुक सकते हैं या अटक सकते हैं. जब कोई ब्राउज़र मेमोरी को फिर से हासिल करता है, तो JS का एक्ज़ीक्यूशन रुक जाता है. इसलिए, बार-बार गार्बेज इकट्ठा करने वाला ब्राउज़र, एक्ज़ीक्यूशन को हमारी पसंद से ज़्यादा बार रोक सकता है. पेजों को जैंक फ़्री रखने के लिए, मेमोरी लीक और बार-बार जीसी पॉज़ से बचें.
- रनटाइम के दौरान, लंबे समय तक चलने वाली JavaScript, मुख्य थ्रेड को ब्लॉक कर सकती है. इससे पेज काम नहीं करते. काम को छोटे-छोटे हिस्सों में बांटने से, रिस्पॉन्सिवनेस से जुड़ी समस्याओं को कम किया जा सकता है. इसके लिए, शेड्यूल करने के लिए
requestAnimationFrame()याrequestIdleCallback()का इस्तेमाल करें. इससे पेज के रिस्पॉन्स में लगने वाले समय (आईएनपी) को बेहतर बनाने में मदद मिल सकती है.
JavaScript डिलीवरी की लागत कम करने के पैटर्न
जब आपको JavaScript के लिए, पार्स/कंपाइल और नेटवर्क ट्रांसमिट के समय को कम रखना हो, तो कुछ पैटर्न आपकी मदद कर सकते हैं. जैसे, रूट-आधारित चंकिंग या PRPL.
PRPL
PRPL (पुश, रेंडर, प्री-कैश, लेज़ी-लोड) एक ऐसा पैटर्न है जो कोड को अलग-अलग हिस्सों में बांटने और कैश मेमोरी में सेव करने की प्रोसेस को ऑप्टिमाइज़ करता है. इससे इंटरैक्टिविटी बेहतर होती है:

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

Wego, पीआरपीएल का इस्तेमाल करने वाली एक साइट है. यह अपने रूट के लिए पार्स करने में लगने वाले समय को कम रखती है. इससे यह बहुत जल्दी इंटरैक्टिव हो जाती है. ऊपर दी गई कई अन्य साइटों ने JS की लागत को कम करने के लिए, कोड-स्प्लिटिंग और परफ़ॉर्मेंस बजट को अपनाया.
प्रोग्रेसिव बूटस्ट्रैपिंग
कई साइटें, इंटरैक्टिविटी की कीमत पर कॉन्टेंट की विज़िबिलिटी को ऑप्टिमाइज़ करती हैं. अगर आपके पास बड़े JavaScript बंडल हैं, तो फ़र्स्ट पेंट को तेज़ी से लोड करने के लिए, डेवलपर कभी-कभी सर्वर-साइड रेंडरिंग का इस्तेमाल करते हैं. इसके बाद, JavaScript फ़ेच होने पर, इवेंट हैंडलर अटैच करने के लिए इसे "अपग्रेड" करते हैं.
सावधान रहें — इसके अपने खर्चे होते हैं. आम तौर पर, बड़ा एचटीएमएल रिस्पॉन्स भेजा जाता है, जिससे इंटरैक्टिविटी को बेहतर बनाया जा सकता है. हालांकि, इससे उपयोगकर्ता को ऐसी स्थिति का सामना करना पड़ सकता है जहां आधा अनुभव तब तक इंटरैक्टिव नहीं हो सकता, जब तक JavaScript प्रोसेसिंग पूरी नहीं हो जाती.
प्रोग्रेसिव बूटस्ट्रैपिंग एक बेहतर तरीका हो सकता है. कम से कम फ़ंक्शन वाला पेज भेजें. इसमें सिर्फ़ मौजूदा रूट के लिए ज़रूरी एचटीएमएल/JS/सीएसएस शामिल हो. ज़्यादा संसाधन उपलब्ध होने पर, ऐप्लिकेशन लेज़ी-लोड हो सकता है और ज़्यादा सुविधाएं अनलॉक कर सकता है.
स्क्रीन पर दिखने वाले कॉन्टेंट के हिसाब से कोड लोड करना सबसे सही तरीका है. PRPL और प्रोग्रेसिव बूटस्ट्रैपिंग ऐसे पैटर्न हैं जिनकी मदद से ऐसा किया जा सकता है.
मीटिंग में सामने आए नतीजे
कम स्पीड वाले नेटवर्क के लिए, ट्रांसमिशन साइज़ बहुत अहम होता है. सीपीयू बाउंड डिवाइसों के लिए, पार्स करने में लगने वाला समय अहम होता है. इनकी संख्या कम रखना ज़रूरी है.
टीमों को JavaScript ट्रांसमिशन और पार्स/कंपाइल करने में लगने वाले समय को कम रखने के लिए, परफ़ॉर्मेंस बजट को सख्ती से लागू करने में सफलता मिली है. एलेक्स रसेल का "क्या आपके पास इसे खरीदने के लिए पैसे हैं?: Real-world Web Performance Budgets" देखें.
अगर मोबाइल डिवाइसों को टारगेट करने वाली साइट बनाई जा रही है, तो उसे ऐसे हार्डवेयर पर डेवलप करें जो आपके टारगेट ऑडियंस के डिवाइसों से मिलता-जुलता हो. साथ ही, JavaScript को पार्स/कंपाइल करने में लगने वाले समय को कम रखें. इसके अलावा, परफ़ॉर्मेंस बजट का इस्तेमाल करें, ताकि आपकी टीम JavaScript की लागत पर नज़र रख सके.
ज़्यादा जानें
- Chrome Dev Summit 2017 - Modern Loading Best Practices
- JavaScript स्टार्ट-अप परफ़ॉर्मेंस
- वेब परफ़ॉर्मेंस की समस्या को हल करना — नोलन लॉसन
- क्या आपके पास इसे खरीदने के लिए पैसे हैं? असल दुनिया में परफ़ॉर्मेंस बजट — ऐलेक्स रसेल
- वेब फ़्रेमवर्क और लाइब्रेरी का आकलन करना — क्रिस्टोफ़र बैक्सटर
- Cloudflare के Brotli के साथ एक्सपेरिमेंट करने के नतीजे, ताकि कंप्रेस किया जा सके. ध्यान दें कि डाइनैमिक Brotli को बेहतर क्वालिटी पर सेट करने से, पेज को रेंडर होने में ज़्यादा समय लग सकता है. इसलिए, सोच-समझकर फ़ैसला लें. इसके बजाय, आपको स्टैटिक तरीके से कंप्रेस करना चाहिए.)
- Performance Futures — सैम सैकोन