जानें कि ब्राउज़र प्रीलोड स्कैनर क्या है, यह परफ़ॉर्मेंस को बेहतर बनाने में कैसे मदद करता है, और इसके काम करने के तरीके में रुकावट डालने से कैसे बचा जा सकता है.
पेज स्पीड को ऑप्टिमाइज़ करने का एक ऐसा पहलू जिस पर ध्यान नहीं दिया जाता है, वह है ब्राउज़र के अंदरूनी हिस्सों के बारे में थोड़ी जानकारी होना. ब्राउज़र, परफ़ॉर्मेंस को बेहतर बनाने के लिए कुछ ऑप्टिमाइज़ेशन करते हैं. ये ऑप्टिमाइज़ेशन, डेवलपर के तौर पर हम नहीं कर सकते. हालांकि, ऐसा तब तक ही होता है, जब तक कि उन ऑप्टिमाइज़ेशन को अनजाने में रोका न जाए.
ब्राउज़र के इंटरनल ऑप्टिमाइज़ेशन को समझने के लिए, ब्राउज़र प्रीलोड स्कैनर को समझना ज़रूरी है. इस पोस्ट में बताया गया है कि प्रीलोड स्कैनर कैसे काम करता है. साथ ही, यह भी बताया गया है कि इसके काम करने के तरीके में रुकावट डालने से कैसे बचा जा सकता है.
प्रीलोड स्कैनर क्या है?
हर ब्राउज़र में एक मुख्य एचटीएमएल पार्सर होता है, जो रॉ मार्कअप को टोकनाइज़ करता है और उसे ऑब्जेक्ट मॉडल में प्रोसेस करता है. यह प्रोसेस तब तक चलती रहती है, जब तक पार्सर को कोई ब्लॉक करने वाला रिसॉर्स नहीं मिल जाता. जैसे, <link> एलिमेंट के साथ लोड की गई स्टाइलशीट या async या defer एट्रिब्यूट के बिना <script> एलिमेंट के साथ लोड की गई स्क्रिप्ट.
<link> एलिमेंट में चला जाता है. इससे ब्राउज़र, बाकी दस्तावेज़ को पार्स नहीं कर पाता या उसे रेंडर नहीं कर पाता. ऐसा तब तक होता है, जब तक सीएसएस डाउनलोड और पार्स नहीं हो जाती.
सीएसएस फ़ाइलों के मामले में, रेंडरिंग को ब्लॉक कर दिया जाता है, ताकि फ़्लैश ऑफ़ अनस्टाइल्ड कॉन्टेंट (एफ़ओयूसी) को रोका जा सके. यह तब होता है, जब किसी पेज पर स्टाइल लागू करने से पहले, उसका अनस्टाइल्ड वर्शन कुछ समय के लिए देखा जा सकता है.
अगर ब्राउज़र को defer या async एट्रिब्यूट के बिना <script> एलिमेंट मिलते हैं, तो वह पेज को पार्स और रेंडर होने से भी रोकता है.
इसकी वजह यह है कि ब्राउज़र को यह पक्का नहीं पता होता कि कोई स्क्रिप्ट, डीओएम में बदलाव करेगी या नहीं. ऐसा तब होता है, जब प्राइमरी एचटीएमएल पार्सर अब भी अपना काम कर रहा हो. इसलिए, JavaScript को दस्तावेज़ के आखिर में लोड करना एक आम तरीका है. इससे, पार्सिंग और रेंडरिंग ब्लॉक होने के असर को कम किया जा सकता है.
ये ऐसी वजहें हैं जिनकी वजह से ब्राउज़र को पार्सिंग और रेंडरिंग, दोनों को ब्लॉक करना चाहिए. हालांकि, इनमें से किसी भी ज़रूरी चरण को ब्लॉक करना सही नहीं है. ऐसा करने से, अन्य ज़रूरी रिसॉर्स को खोजने में देरी हो सकती है. अच्छी बात यह है कि ब्राउज़र, इन समस्याओं को कम करने की पूरी कोशिश करते हैं. इसके लिए, वे प्रीलोड स्कैनर नाम के सेकंडरी एचटीएमएल पार्सर का इस्तेमाल करते हैं.
<body> एलिमेंट में इमेज मार्कअप को प्रोसेस करने से पहले, सीएसएस को लोड और प्रोसेस करता है. हालांकि, प्रीलोड स्कैनर, रॉ मार्कअप में आगे देखकर उस इमेज रिसॉर्स को ढूंढ सकता है और मुख्य एचटीएमएल पार्सर के अनब्लॉक होने से पहले उसे लोड करना शुरू कर सकता है.
प्रीलोड स्कैनर का काम अनुमान लगाना होता है. इसका मतलब है कि यह रॉ मार्कअप की जांच करता है, ताकि मुख्य एचटीएमएल पार्सर के खोजने से पहले ही संसाधनों को फ़ेच किया जा सके.
यह कैसे पता लगाएं कि प्रीलोड स्कैनर काम कर रहा है या नहीं
प्रीलोड स्कैनर का इस्तेमाल इसलिए किया जाता है, क्योंकि रेंडरिंग और पार्सिंग की प्रोसेस ब्लॉक हो जाती है. अगर परफ़ॉर्मेंस से जुड़ी ये दो समस्याएं कभी नहीं होतीं, तो प्रीलोड स्कैनर ज़्यादा काम का नहीं होता. कोई वेब पेज, प्रीलोड स्कैनर से फ़ायदा पाता है या नहीं, यह जानने के लिए इन ब्लॉकिंग फ़ेनोमेना को समझना ज़रूरी है. इसके लिए, अनुरोधों में कुछ समय की देरी की जा सकती है, ताकि यह पता लगाया जा सके कि प्रीलोड स्कैनर कहां काम कर रहा है.
उदाहरण के लिए, स्टाइलशीट के साथ बेसिक टेक्स्ट और इमेज वाले इस पेज को देखें. सीएसएस फ़ाइलें, रेंडरिंग और पार्सिंग, दोनों को ब्लॉक करती हैं. इसलिए, प्रॉक्सी सेवा का इस्तेमाल करके, स्टाइलशीट के लिए दो सेकंड की देरी सेट की जाती है. इस देरी की वजह से, नेटवर्क वॉटरफ़ॉल में यह देखना आसान हो जाता है कि प्रीलोड स्कैनर कहां काम कर रहा है.
वॉटरफ़ॉल में देखा जा सकता है कि प्रीलोड स्कैनर, <img> एलिमेंट को खोज लेता है. भले ही, रेंडरिंग और दस्तावेज़ को पार्स करने की प्रोसेस ब्लॉक हो. इस ऑप्टिमाइज़ेशन के बिना, ब्राउज़र ब्लॉक करने की अवधि के दौरान चीज़ों को फ़ेच नहीं कर सकता. साथ ही, ज़्यादा रिसॉर्स अनुरोध एक साथ होने के बजाय एक के बाद एक होंगे.
खिलौने के इस उदाहरण को समझने के बाद, आइए असल दुनिया के कुछ ऐसे पैटर्न पर नज़र डालते हैं जहां प्रीलोड स्कैनर को मात दी जा सकती है. साथ ही, उन्हें ठीक करने के लिए क्या किया जा सकता है.
async स्क्रिप्ट इंजेक्ट की गईं
मान लें कि आपके <head> में एचटीएमएल है, जिसमें इस तरह की कुछ इनलाइन JavaScript शामिल है:
<script>
const scriptEl = document.createElement('script');
scriptEl.src = '/yall.min.js';
document.head.appendChild(scriptEl);
</script>
इंजेक्ट की गई स्क्रिप्ट, डिफ़ॉल्ट रूप से async होती हैं. इसलिए, जब इस स्क्रिप्ट को इंजेक्ट किया जाता है, तो यह इस तरह से काम करेगी जैसे कि इस पर async एट्रिब्यूट लागू किया गया हो. इसका मतलब है कि यह जल्द से जल्द चलेगा और रेंडरिंग को ब्लॉक नहीं करेगा. यह तो बहुत बढ़िया है, है न? हालांकि, अगर आपको लगता है कि यह इनलाइन <script>, किसी बाहरी सीएसएस फ़ाइल को लोड करने वाले <link> एलिमेंट के बाद आता है, तो आपको खराब नतीजा मिलेगा:
async स्क्रिप्ट मौजूद है. प्रीलोड स्कैनर, रेंडर ब्लॉकिंग फ़ेज़ के दौरान स्क्रिप्ट का पता नहीं लगा सकता, क्योंकि इसे क्लाइंट पर इंजेक्ट किया जाता है.
आइए, इस बारे में विस्तार से जानते हैं:
- 0 सेकंड पर, मुख्य दस्तावेज़ का अनुरोध किया जाता है.
- 1.4 सेकंड पर, नेविगेशन अनुरोध का पहला बाइट मिलता है.
- दो सेकंड पर, सीएसएस और इमेज का अनुरोध किया जाता है.
- पार्सर, स्टाइलशीट को लोड होने से रोकता है. साथ ही,
asyncस्क्रिप्ट को इंजेक्ट करने वाला इनलाइन JavaScript, उस स्टाइलशीट के बाद 2.6 सेकंड पर आता है. इस वजह से, स्क्रिप्ट से मिलने वाली सुविधा जल्द से जल्द उपलब्ध नहीं हो पाती.
यह तरीका सही नहीं है, क्योंकि स्क्रिप्ट के लिए अनुरोध, स्टाइलशीट के डाउनलोड होने के बाद ही किया जाता है. इससे स्क्रिप्ट को जल्द से जल्द चलाने में देरी होती है. इसके उलट, <img> एलिमेंट को सर्वर से मिले मार्कअप में खोजा जा सकता है. इसलिए, प्रीलोड स्कैनर इसे खोज लेता है.
अगर स्क्रिप्ट को डीओएम में इंजेक्ट करने के बजाय, async एट्रिब्यूट के साथ सामान्य <script> टैग का इस्तेमाल किया जाए, तो क्या होगा?
<script src="/yall.min.js" async></script>
इसका नतीजा यह होता है:
async <script> एलिमेंट होता है. प्रीलोड स्कैनर, रेंडर ब्लॉकिंग फ़ेज़ के दौरान स्क्रिप्ट का पता लगाता है और उसे सीएसएस के साथ लोड करता है.
ऐसा लग सकता है कि इन समस्याओं को rel=preload का इस्तेमाल करके ठीक किया जा सकता है. इससे निश्चित तौर पर मदद मिलेगी, लेकिन इसके कुछ खराब असर भी हो सकते हैं. आखिरकार, ऐसी समस्या को ठीक करने के लिए rel=preload का इस्तेमाल क्यों करें जिससे डीओएम में <script> एलिमेंट को इंजेक्ट न करके बचा जा सकता है?
async स्क्रिप्ट शामिल है. हालांकि, async स्क्रिप्ट को पहले से लोड किया गया है, ताकि यह पक्का किया जा सके कि इसे जल्दी खोजा जा सके.
पहले से लोड करने से यहां समस्या "ठीक" हो जाती है, लेकिन इससे एक नई समस्या पैदा होती है: पहले दो डेमो में async स्क्रिप्ट, <head> में लोड होने के बावजूद, "कम" प्राथमिकता पर लोड होती है. वहीं, स्टाइलशीट "सबसे ज़्यादा" प्राथमिकता पर लोड होती है. आखिरी डेमो में, जहां async स्क्रिप्ट पहले से लोड है, वहां स्टाइलशीट अब भी "सबसे ज़्यादा" प्राथमिकता पर लोड होती है. हालांकि, स्क्रिप्ट की प्राथमिकता को "ज़्यादा" पर प्रमोट कर दिया गया है.
जब किसी रिसॉर्स की प्राथमिकता बढ़ाई जाती है, तो ब्राउज़र उसे ज़्यादा बैंडविड्थ देता है. इसका मतलब है कि स्टाइलशीट को सबसे ज़्यादा प्राथमिकता मिलने के बावजूद, स्क्रिप्ट की प्राथमिकता बढ़ने से बैंडविड्थ के लिए मुकाबला हो सकता है. ऐसा धीमे इंटरनेट कनेक्शन या बहुत बड़े रिसॉर्स की वजह से हो सकता है.
इसका जवाब आसान है: अगर स्टार्टअप के दौरान किसी स्क्रिप्ट की ज़रूरत है, तो उसे DOM में इंजेक्ट करके प्रीलोड स्कैनर को न रोकें. <script> एलिमेंट की प्लेसमेंट के साथ-साथ, defer और async जैसे एट्रिब्यूट के साथ ज़रूरत के हिसाब से एक्सपेरिमेंट करें.
JavaScript की मदद से लेज़ी लोडिंग करना
लेज़ी लोडिंग, डेटा बचाने का एक बेहतरीन तरीका है. इसे अक्सर इमेज पर लागू किया जाता है. हालांकि, कभी-कभी लेज़ी लोडिंग की सुविधा, "पेज के ऊपरी हिस्से" में मौजूद इमेज पर गलत तरीके से लागू हो जाती है.
इससे, प्रीलोड स्कैनर के लिए संसाधन खोजने में समस्याएं आ सकती हैं. साथ ही, किसी इमेज का रेफ़रंस खोजने, उसे डाउनलोड करने, डिकोड करने, और दिखाने में बेवजह देरी हो सकती है. उदाहरण के लिए, इस इमेज मार्कअप को देखें:
<img data-src="/sand-wasp.jpg" alt="Sand Wasp" width="384" height="255">
JavaScript की मदद से काम करने वाले लेज़ी लोडर में, data- प्रीफ़िक्स का इस्तेमाल करना एक आम पैटर्न है. जब इमेज को स्क्रोल करके व्यूपोर्ट में लाया जाता है, तो लेज़ी लोडर data- प्रीफ़िक्स को हटा देता है. इसका मतलब है कि पिछले उदाहरण में, data-src, src बन जाता है. इस अपडेट से, ब्राउज़र को संसाधन फ़ेच करने का निर्देश मिलता है.
यह पैटर्न तब तक समस्या नहीं बनता, जब तक इसे उन इमेज पर लागू नहीं किया जाता जो स्टार्टअप के दौरान व्यूपोर्ट में मौजूद होती हैं. प्रीलोड स्कैनर, data-src एट्रिब्यूट को src (या srcset) एट्रिब्यूट की तरह नहीं पढ़ता. इसलिए, इमेज का रेफ़रंस पहले नहीं मिलता. इससे भी खराब बात यह है कि इमेज तब तक लोड नहीं होती, जब तक लेज़ी लोडर JavaScript डाउनलोड, कंपाइल, और एक्ज़ीक्यूट नहीं हो जाता.
इमेज के साइज़ के आधार पर, यह सबसे बड़े एलिमेंट को रेंडर करने में लगने वाले समय (एलसीपी) के लिए एक ज़रूरी एलिमेंट हो सकता है. इमेज का साइज़, व्यूपोर्ट के साइज़ पर निर्भर हो सकता है. जब प्रीलोड स्कैनर, इमेज रिसॉर्स को समय से पहले फ़ेच नहीं कर पाता है, तो एलसीपी पर असर पड़ता है. ऐसा तब हो सकता है, जब पेज की स्टाइलशीट रेंडरिंग को ब्लॉक कर रही हों.
इसका समाधान, इमेज मार्कअप में बदलाव करना है:
<img src="/sand-wasp.jpg" alt="Sand Wasp" width="384" height="255">
यह उन इमेज के लिए सबसे सही पैटर्न है जो स्टार्टअप के दौरान व्यूपोर्ट में होती हैं. ऐसा इसलिए, क्योंकि प्रीलोड स्कैनर, इमेज रिसॉर्स को ज़्यादा तेज़ी से खोजेगा और फ़ेच करेगा.
इस आसान उदाहरण में, धीमे कनेक्शन पर एलसीपी में 100 मिलीसेकंड का सुधार हुआ है. यह बहुत बड़ा सुधार नहीं लग सकता है. हालांकि, यह तब होता है, जब आपको लगता है कि समाधान एक क्विक मार्कअप फ़िक्स है और ज़्यादातर वेब पेज, उदाहरणों के इस सेट से ज़्यादा जटिल हैं. इसका मतलब है कि एलसीपी कैंडिडेट को कई अन्य रिसॉर्स के साथ बैंडविड्थ के लिए मुकाबला करना पड़ सकता है. इसलिए, इस तरह के ऑप्टिमाइज़ेशन ज़्यादा अहम हो जाते हैं.
सीएसएस बैकग्राउंड इमेज
याद रखें कि ब्राउज़र का प्रीलोड स्कैनर, मार्कअप को स्कैन करता है. यह अन्य तरह के रिसॉर्स को स्कैन नहीं करता. जैसे, सीएसएस, जिसमें background-image प्रॉपर्टी से रेफ़र की गई इमेज को फ़ेच करना शामिल हो सकता है.
एचटीएमएल की तरह ही, ब्राउज़र सीएसएस को अपने ऑब्जेक्ट मॉडल में प्रोसेस करते हैं. इसे CSSOM कहा जाता है. अगर सीएसएसओएम के बनने के दौरान बाहरी रिसॉर्स का पता चलता है, तो उन रिसॉर्स के लिए अनुरोध उसी समय किया जाता है, न कि प्रीलोड स्कैनर से.
मान लें कि आपके पेज का एलसीपी कैंडिडेट, सीएसएस background-image प्रॉपर्टी वाला एलिमेंट है. संसाधन लोड होने पर, ये चीज़ें होती हैं:
background-image प्रॉपर्टी (तीसरी लाइन) वाला एलिमेंट है. अनुरोध की गई इमेज तब तक फ़ेच नहीं होती, जब तक सीएसएस पार्सर उसे ढूंढ नहीं लेता.
इस मामले में, प्रीलोड स्कैनर को हराया नहीं जाता, बल्कि वह इसमें शामिल नहीं होता. इसके बावजूद, अगर पेज पर एलसीपी एलिमेंट, background-image सीएसएस प्रॉपर्टी से है, तो आपको उस इमेज को पहले से लोड करना होगा:
<!-- Make sure this is in the <head> below any
stylesheets, so as not to block them from loading -->
<link rel="preload" as="image" href="lcp-image.jpg">
rel=preload हिंट छोटा है, लेकिन इससे ब्राउज़र को इमेज को सामान्य से ज़्यादा तेज़ी से खोजने में मदद मिलती है:
background-image प्रॉपर्टी (तीसरी लाइन) वाला एलिमेंट है. rel=preload हिंट की मदद से, ब्राउज़र को इमेज ढूंढने में करीब 250 मिलीसेकंड कम समय लगता है.
rel=preload हिंट की मदद से, एलसीपी कैंडिडेट का पता जल्दी चल जाता है. इससे एलसीपी का समय कम हो जाता है. इस हिंट से समस्या को ठीक करने में मदद मिलती है. हालांकि, बेहतर विकल्प यह हो सकता है कि आप यह आकलन करें कि आपकी इमेज एलसीपी कैंडिडेट को सीएसएस से लोड करना है या नहीं. <img> टैग की मदद से, व्यूपोर्ट के लिए सही इमेज लोड करने पर ज़्यादा कंट्रोल मिलता है. साथ ही, प्रीलोड स्कैनर को इसे खोजने की अनुमति मिलती है.
बहुत सारे रिसॉर्स को इनलाइन करना
इनलाइनिंग एक ऐसी प्रोसेस है जिसमें किसी संसाधन को एचटीएमएल के अंदर रखा जाता है. <style> एलिमेंट में स्टाइलशीट और <script> एलिमेंट में स्क्रिप्ट को इनलाइन किया जा सकता है. साथ ही, base64 एन्कोडिंग का इस्तेमाल करके, किसी भी अन्य संसाधन को इनलाइन किया जा सकता है.
संसाधनों को इनलाइन करना, उन्हें डाउनलोड करने से ज़्यादा तेज़ हो सकता है. ऐसा इसलिए, क्योंकि संसाधन के लिए अलग से अनुरोध नहीं किया जाता. यह दस्तावेज़ में ही मौजूद होता है और तुरंत लोड हो जाता है. हालांकि, इसके कुछ बड़े नुकसान भी हैं:
- अगर एचटीएमएल को कैश मेमोरी में सेव नहीं किया जा रहा है, तो इनलाइन किए गए रिसॉर्स कभी भी कैश मेमोरी में सेव नहीं किए जाते. अगर एचटीएमएल रिस्पॉन्स डाइनैमिक है, तो ऐसा नहीं किया जा सकता. इससे परफ़ॉर्मेंस पर असर पड़ता है, क्योंकि इनलाइन किए गए संसाधनों को फिर से इस्तेमाल नहीं किया जा सकता.
- एचटीएमएल को कैश मेमोरी में सेव किया जा सकता है, लेकिन इनलाइन संसाधनों को दस्तावेज़ों के बीच शेयर नहीं किया जाता. इससे, बाहरी फ़ाइलों की तुलना में कैश मेमोरी की क्षमता कम हो जाती है. बाहरी फ़ाइलों को कैश मेमोरी में सेव किया जा सकता है और पूरे ऑरिजिन में फिर से इस्तेमाल किया जा सकता है.
- अगर आपने बहुत ज़्यादा इनलाइन किया है, तो प्रीलोड स्कैनर को दस्तावेज़ में बाद में मौजूद रिसॉर्स खोजने में देरी होती है. ऐसा इसलिए होता है, क्योंकि उस अतिरिक्त, इनलाइन किए गए कॉन्टेंट को डाउनलोड करने में ज़्यादा समय लगता है.
उदाहरण के तौर पर इस पेज को देखें. कुछ मामलों में, एलसीपी कैंडिडेट पेज के सबसे ऊपर मौजूद इमेज होती है. साथ ही, सीएसएस एक अलग फ़ाइल में होती है, जिसे <link> एलिमेंट लोड करता है. इस पेज पर चार वेब फ़ॉन्ट भी इस्तेमाल किए गए हैं. इन्हें सीएसएस रिसॉर्स से अलग फ़ाइलों के तौर पर अनुरोध किया गया है.
<img> एलिमेंट से लोड की गई इमेज है. हालांकि, प्रीलोड स्कैनर को इसका पता चल जाता है, क्योंकि पेज लोड के लिए ज़रूरी सीएसएस और फ़ॉन्ट अलग-अलग रिसॉर्स में लोड होते हैं. इससे प्रीलोड स्कैनर को अपना काम करने में देरी नहीं होती.
अगर सीएसएस और सभी फ़ॉन्ट, base64 रिसॉर्स के तौर पर इनलाइन किए गए हों, तो क्या होगा?
<img> एलिमेंट से लोड की गई इमेज है. हालांकि, `` में सीएसएस और उसके चार फ़ॉन्ट रिसॉर्स को इनलाइन करने की वजह से, प्रीलोड स्कैनर को इमेज का पता लगाने में देरी होती है. ऐसा तब तक होता है, जब तक वे रिसॉर्स पूरी तरह से डाउनलोड नहीं हो जाते.
इस उदाहरण में, इनलाइन करने से एलसीपी पर बुरा असर पड़ता है. साथ ही, सामान्य तौर पर परफ़ॉर्मेंस पर भी असर पड़ता है. पेज का वह वर्शन जिसमें कुछ भी इनलाइन नहीं किया गया है, एलसीपी इमेज को करीब 3.5 सेकंड में पेंट करता है. जिस पेज पर सब कुछ इनलाइन होता है वह सात सेकंड से ज़्यादा समय तक एलसीपी इमेज को पेंट नहीं करता.
यहां प्रीलोड स्कैनर के अलावा, और भी कई चीज़ें काम करती हैं. फ़ॉन्ट को इनलाइन करना सही रणनीति नहीं है, क्योंकि बाइनरी रिसॉर्स के लिए base64 एक सही फ़ॉर्मैट नहीं है. एक और वजह यह है कि बाहरी फ़ॉन्ट रिसॉर्स तब तक डाउनलोड नहीं होते, जब तक सीएसएसओएम उन्हें ज़रूरी नहीं मानता. जब उन फ़ॉन्ट को base64 के तौर पर इनलाइन किया जाता है, तो वे डाउनलोड हो जाते हैं. भले ही, मौजूदा पेज के लिए उनकी ज़रूरत हो या न हो.
क्या प्रीलोड करने से यहां चीज़ें बेहतर हो सकती हैं? बेशक। एलसीपी इमेज को पहले से लोड किया जा सकता है और एलसीपी के समय को कम किया जा सकता है. हालांकि, इनलाइन रिसॉर्स की मदद से, कैश मेमोरी में सेव न किए जा सकने वाले एचटीएमएल को बढ़ाने से, परफ़ॉर्मेंस पर अन्य नकारात्मक असर पड़ते हैं. साइट का पहला एलिमेंट लोड होने में लगने वाले समय (एफ़सीपी) पर भी इस पैटर्न का असर पड़ता है. पेज के उस वर्शन में जहां कुछ भी इनलाइन नहीं है, एफ़सीपी करीब 2.7 सेकंड है. जिस वर्शन में सब कुछ इनलाइन है उसमें एफ़सीपी करीब 5.8 सेकंड है.
एचटीएमएल में इनलाइन कॉन्टेंट डालते समय बहुत सावधानी बरतें. खास तौर पर, base64 कोड में बदले गए संसाधनों के मामले में. आम तौर पर, ऐसा करने का सुझाव नहीं दिया जाता है. हालांकि, बहुत छोटे रिसॉर्स के लिए ऐसा किया जा सकता है. इनलाइन का इस्तेमाल कम से कम करें, क्योंकि ज़्यादा इनलाइन करने से गड़बड़ी हो सकती है.
क्लाइंट-साइड JavaScript की मदद से मार्कअप रेंडर करना
इसमें कोई शक नहीं है कि JavaScript से पेज स्पीड पर असर पड़ता है. डेवलपर, इंटरैक्टिविटी देने के लिए इस पर निर्भर रहते हैं. साथ ही, कॉन्टेंट डिलीवर करने के लिए भी इस पर भरोसा किया जाता है. इससे डेवलपर को कुछ मामलों में बेहतर अनुभव मिलता है. हालांकि, डेवलपर को मिलने वाले फ़ायदे हमेशा उपयोगकर्ताओं के लिए फ़ायदेमंद नहीं होते.
प्रीलोड स्कैनर को मात देने वाला एक पैटर्न, क्लाइंट-साइड JavaScript के साथ मार्कअप को रेंडर करना है:
जब मार्कअप पेलोड, ब्राउज़र में JavaScript में मौजूद होते हैं और पूरी तरह से JavaScript से रेंडर होते हैं, तो उस मार्कअप में मौजूद कोई भी संसाधन, प्रीलोड स्कैनर को नहीं दिखता. इससे ज़रूरी रिसॉर्स को खोजने में देरी होती है. इससे एलसीपी पर असर पड़ता है. इन उदाहरणों के मामले में, एलसीपी इमेज के लिए अनुरोध में काफ़ी देरी होती है. ऐसा तब होता है, जब इसकी तुलना सर्वर से रेंडर किए गए ऐसे अनुभव से की जाती है जिसमें JavaScript की ज़रूरत नहीं होती.
यह इस लेख के मुख्य विषय से थोड़ा अलग है. हालांकि, क्लाइंट पर मार्कअप रेंडर करने के असर, प्रीलोड स्कैनर को मात देने से कहीं ज़्यादा हैं. उदाहरण के लिए, किसी ऐसे अनुभव को बेहतर बनाने के लिए JavaScript का इस्तेमाल करना जिसके लिए इसकी ज़रूरत नहीं है, प्रोसेसिंग में लगने वाले समय को बढ़ा देता है. इससे पेज के रिस्पॉन्स में लगने वाले समय (आईएनपी) पर असर पड़ सकता है. क्लाइंट पर बहुत ज़्यादा मार्कअप रेंडर करने से, ज़्यादा समय लेने वाले टास्क जनरेट होने की संभावना ज़्यादा होती है. ऐसा तब होता है, जब सर्वर से उतना ही मार्कअप भेजा जाता है. इसकी वजह यह है कि ब्राउज़र, सर्वर से मार्कअप को स्ट्रीम करते हैं और रेंडरिंग को इस तरह से बांटते हैं कि ज़्यादा समय लेने वाले काम सीमित हो जाते हैं. हालांकि, JavaScript में अतिरिक्त प्रोसेसिंग की वजह से भी ऐसा होता है. दूसरी ओर, क्लाइंट-साइड पर रेंडर किए गए मार्कअप को एक ही टास्क के तौर पर हैंडल किया जाता है. इससे पेज के आईएनपी पर असर पड़ सकता है.
इस समस्या का समाधान इस सवाल के जवाब पर निर्भर करता है: क्या कोई ऐसी वजह है जिसकी वजह से आपके पेज का मार्कअप, क्लाइंट पर रेंडर होने के बजाय सर्वर से नहीं दिया जा सकता? अगर इसका जवाब "नहीं" है, तो जहां भी संभव हो वहां सर्वर-साइड रेंडरिंग (एसएसआर) या स्टैटिक तौर पर जनरेट किए गए मार्कअप का इस्तेमाल किया जाना चाहिए. इससे प्रीलोड स्कैनर को समय से पहले ज़रूरी रिसॉर्स खोजने और उन्हें फ़ेच करने में मदद मिलेगी.
अगर आपके पेज के मार्कअप के कुछ हिस्सों में फ़ंक्शन जोड़ने के लिए, JavaScript की ज़रूरत पड़ती है, तो एसएसआर की मदद से ऐसा किया जा सकता है. इसके लिए, वैनिला JavaScript या हाइड्रेशन का इस्तेमाल करें. इससे आपको दोनों के फ़ायदे मिलेंगे.
प्रीलोड स्कैनर की मदद करना
प्रीलोड स्कैनर, ब्राउज़र का एक बेहद असरदार ऑप्टिमाइज़ेशन है. इसकी मदद से, स्टार्टअप के दौरान पेज तेज़ी से लोड होते हैं. ऐसे पैटर्न से बचें जो ज़रूरी रिसॉर्स को समय से पहले खोजने की ब्राउज़र की क्षमता को कम करते हैं. इससे न सिर्फ़ आपके लिए डेवलपमेंट आसान हो जाता है, बल्कि उपयोगकर्ताओं को बेहतर अनुभव भी मिलता है. इससे कई मेट्रिक में बेहतर नतीजे मिलेंगे. इनमें कुछ Web Vitals भी शामिल है.
इस पोस्ट में दी गई जानकारी को फिर से दोहराने के लिए, यहां कुछ बातें बताई गई हैं:
- ब्राउज़र का प्रीलोड स्कैनर, एक सेकंडरी एचटीएमएल पार्सर होता है. अगर प्राइमरी पार्सर ब्लॉक हो जाता है, तो यह उससे पहले स्कैन करता है, ताकि उन रिसॉर्स को खोजा जा सके जिन्हें जल्दी फ़ेच किया जा सकता है.
- प्रीलोड स्कैनर उन रिसॉर्स का पता नहीं लगा सकता जो शुरुआती नेविगेशन अनुरोध पर, सर्वर से मिले मार्कअप में मौजूद नहीं होते. प्रीलोड स्कैनर को इन तरीकों से रोका जा सकता है. हालांकि, इनके अलावा और भी तरीके हो सकते हैं:
- JavaScript की मदद से DOM में रिसॉर्स इंजेक्ट करना. ये रिसॉर्स स्क्रिप्ट, इमेज, स्टाइलशीट या ऐसी कोई भी चीज़ हो सकती है जो सर्वर से शुरुआती मार्कअप पेलोड में बेहतर हो.
- JavaScript का इस्तेमाल करके, पेज के सबसे ऊपर दिखने वाले हिस्से में मौजूद इमेज या iframe को लेज़ी लोड करना.
- क्लाइंट पर रेंडरिंग मार्कअप, जिसमें JavaScript का इस्तेमाल करके दस्तावेज़ के सब-रिसोर्स के रेफ़रंस शामिल हो सकते हैं.
- प्रीलोड स्कैनर सिर्फ़ एचटीएमएल को स्कैन करता है. यह अन्य रिसॉर्स के कॉन्टेंट की जांच नहीं करता. खास तौर पर, सीएसएस की जांच नहीं करता. इसमें एलसीपी कैंडिडेट के साथ-साथ, ज़रूरी ऐसेट के रेफ़रंस शामिल हो सकते हैं.
अगर किसी भी वजह से, आपको ऐसे पैटर्न का इस्तेमाल करना ही पड़े जो प्रीलोड स्कैनर की, पेज लोड होने की परफ़ॉर्मेंस को बेहतर बनाने की क्षमता पर बुरा असर डालता है, तो rel=preload रिसॉर्स हिंट का इस्तेमाल करें. अगर rel=preload का इस्तेमाल किया जा रहा है, तो लैब टूल में इसकी जांच करें. इससे यह पक्का किया जा सकेगा कि आपको अपनी पसंद के मुताबिक असर मिल रहा है. आखिर में, बहुत ज़्यादा रिसॉर्स पहले से लोड न करें. ऐसा इसलिए, क्योंकि जब हर चीज़ को प्राथमिकता दी जाती है, तो किसी भी चीज़ को प्राथमिकता नहीं मिलती.
संसाधन
- स्क्रिप्ट-इंजेक्टेड "एसिंक स्क्रिप्ट" को नुकसान पहुंचाने वाला माना जाता है
- ब्राउज़र प्री-लोडर, पेजों को तेज़ी से लोड करने में कैसे मदद करता है
- लोड होने की स्पीड बढ़ाने के लिए, ज़रूरी ऐसेट पहले से लोड करना
- पेज स्पीड को बेहतर बनाने के लिए, नेटवर्क कनेक्शन को पहले से ही सेट अप करना
- सबसे बड़े एलिमेंट को रेंडर करने में लगने वाले समय (एलसीपी) को ऑप्टिमाइज़ करना