ब्राउज़र प्रीलोड स्कैनर से मुकाबला न करें

जानें कि ब्राउज़र प्रीलोड स्कैनर क्या है, यह परफ़ॉर्मेंस को कैसे बेहतर बनाता है, और इससे कैसे बचा जा सकता है.

पेज की स्पीड को ऑप्टिमाइज़ करने के लिए, ब्राउज़र के इंटरनल काम करने के तरीके के बारे में थोड़ा जानना ज़रूरी है. ब्राउज़र, परफ़ॉर्मेंस को बेहतर बनाने के लिए कुछ ऐसे ऑप्टिमाइज़ेशन करते हैं जिन्हें डेवलपर के तौर पर हम नहीं कर सकते. हालांकि, ऐसा तब तक ही होता है, जब तक कि उन ऑप्टिमाइज़ेशन को अनजाने में गलत तरीके से इस्तेमाल न किया जाए.

ब्राउज़र का एक ऐसा ऑप्टिमाइज़ेशन है जिसे समझना ज़रूरी है. यह ब्राउज़र प्रीलोड स्कैनर है. इस पोस्ट में, प्रीलोड स्कैनर के काम करने के तरीके के बारे में बताया गया है. साथ ही, सबसे अहम बात यह है कि इसकी वजह से होने वाली समस्याओं से कैसे बचा जा सकता है.

प्रीलोड स्कैनर क्या है?

हर ब्राउज़र में एक प्राइमरी एचटीएमएल पार्सर होता है, जो रॉ मार्कअप को टेंप्लेट में बदलता है और उसे ऑब्जेक्ट मॉडल में प्रोसेस करता है. यह प्रोसेस तब तक चलती रहती है, जब तक पार्स करने वाला टूल किसी ब्लॉकिंग रिसॉर्स को नहीं ढूंढ लेता. जैसे, <link> एलिमेंट के साथ लोड की गई स्टाइलशीट या async या defer एट्रिब्यूट के बिना <script> एलिमेंट के साथ लोड की गई स्क्रिप्ट.

एचटीएमएल पार्स करने वाले टूल का डायग्राम.
पहला इलस्ट्रेशन: इस इलस्ट्रेशन में बताया गया है कि ब्राउज़र के प्राइमरी एचटीएमएल पार्सर को कैसे ब्लॉक किया जा सकता है. इस मामले में, पार्स करने वाला टूल किसी बाहरी सीएसएस फ़ाइल के लिए <link> एलिमेंट पर पहुंच जाता है. इससे, ब्राउज़र बाकी दस्तावेज़ को तब तक पार्स नहीं कर पाता, जब तक सीएसएस डाउनलोड और पार्स नहीं हो जाती. इसके अलावा, यह किसी भी हिस्से को रेंडर भी नहीं कर पाता.

सीएसएस फ़ाइलों के मामले में, बिना स्टाइल वाले कॉन्टेंट का फ़्लैश (FOUC) रोकने के लिए रेंडरिंग को ब्लॉक किया जाता है. ऐसा तब होता है, जब किसी पेज पर स्टाइल लागू होने से पहले, उसे बिना स्टाइल वाला वर्शन कुछ समय के लिए देखा जा सकता है.

web.dev का होम पेज, स्टाइल के बिना (बाईं ओर) और स्टाइल के साथ (दाईं ओर).
दूसरी इमेज: फ़्लैश ऑन यूज़र क्लिक (एफ़ओयूसी) का सिम्युलेट किया गया उदाहरण. बाईं ओर, स्टाइल के बिना web.dev का होम पेज है. दाईं ओर, स्टाइल लागू किए गए वही पेज है. अगर स्टाइलशीट को डाउनलोड और प्रोसेस किए जाने के दौरान, ब्राउज़र रेंडरिंग को ब्लॉक नहीं करता है, तो स्टाइल न होने की स्थिति फ़्लैश में दिख सकती है.

जब ब्राउज़र को defer या async एट्रिब्यूट के बिना <script> एलिमेंट मिलते हैं, तो वह पेज को पार्स और रेंडर करने से भी रोकता है.

इसकी वजह यह है कि ब्राउज़र यह पक्का नहीं कर सकता कि प्राइमरी एचटीएमएल पार्सर के काम करते समय, कोई स्क्रिप्ट डीओएम में बदलाव करेगी या नहीं. इसलिए, आम तौर पर JavaScript को दस्तावेज़ के आखिर में लोड किया जाता है, ताकि पार्स करने और रेंडर करने पर लगने वाले ब्लॉक के असर कम हो सकें.

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

प्राइमरी एचटीएमएल पार्सर (बाईं ओर) और प्रीलोड स्कैनर (दाईं ओर) का डायग्राम. प्रीलोड स्कैनर, सेकंडरी एचटीएमएल पार्सर होता है.
तीसरा इलस्ट्रेशन: इस इलस्ट्रेशन में दिखाया गया है कि प्रीलोड स्कैनर, प्राइमरी एचटीएमएल पार्सर के साथ मिलकर, एसेट को अनुमानित तौर पर कैसे लोड करता है. यहां प्राइमरी एचटीएमएल पार्सर को ब्लॉक किया जाता है, क्योंकि वह <body> एलिमेंट में इमेज मार्कअप को प्रोसेस करने से पहले, सीएसएस को लोड और प्रोसेस करता है. हालांकि, प्रीलोड स्कैनर, रॉ मार्कअप में आगे की ओर देखकर उस इमेज रिसॉर्स को ढूंढ सकता है और प्राइमरी एचटीएमएल पार्सर को अनब्लॉक करने से पहले उसे लोड करना शुरू कर सकता है.

प्रीलोड स्कैनर की भूमिका अनुमानित होती है. इसका मतलब है कि यह रॉ मार्कअप की जांच करता है, ताकि मुख्य एचटीएमएल पार्स करने वाले टूल से पहले, संसाधनों को फ़ेच किया जा सके.

यह कैसे पता लगाएं कि प्रीलोड स्कैनर कब काम कर रहा है

रेंडरिंग और पार्स करने की सुविधा ब्लॉक होने की वजह से, प्रीलोड स्कैनर मौजूद है. अगर परफ़ॉर्मेंस से जुड़ी ये दोनों समस्याएं कभी नहीं हुई हैं, तो प्रीलोड स्कैनर का इस्तेमाल करना ज़्यादा फ़ायदेमंद नहीं होगा. किसी वेब पेज को पहले से लोड करने वाले स्कैनर से फ़ायदा मिलता है या नहीं, यह इस बात पर निर्भर करता है कि पेज को क्रॉल करने से रोकने के लिए कौनसी तकनीक का इस्तेमाल किया जा रहा है. इसके लिए, अनुरोधों के लिए कुछ समय इंतज़ार किया जा सकता है, ताकि यह पता लगाया जा सके कि प्रीलोड स्कैनर कहां काम कर रहा है.

उदाहरण के लिए, स्टाइलशीट के साथ बुनियादी टेक्स्ट और इमेज वाला यह पेज देखें. सीएसएस फ़ाइलें, रेंडरिंग और पार्स करने, दोनों को ब्लॉक करती हैं. इसलिए, आपको किसी प्रॉक्सी सेवा की मदद से स्टाइलशीट के लिए दो सेकंड की देरी करनी पड़ती है. इस देरी की वजह से, नेटवर्क वॉटरफ़ॉल में यह देखना आसान हो जाता है कि प्रीलोड स्कैनर कहां काम कर रहा है.

WebPageTest के नेटवर्क वॉटरफ़ॉल चार्ट में, स्टाइलशीट पर दो सेकंड की आर्टिफ़िशियल देरी दिखाई गई है.
चौथा इलस्ट्रेशन: WebPageTest का नेटवर्क वॉटरफ़ॉल चार्ट, जिसमें किसी वेब पेज को सिम्युलेट किए गए 3G कनेक्शन पर, मोबाइल डिवाइस पर Chrome पर चलाया गया है. स्टाइलशीट लोड होने से पहले, प्रॉक्सी की मदद से दो सेकंड तक उसे लोड होने से रोका जाता है. हालांकि, मार्कअप पेलोड में बाद में मौजूद इमेज को प्रीलोड स्कैनर ढूंढ लेता है.

जैसा कि वॉटरफ़ॉल में देखा जा सकता है, प्रीलोड स्कैनर <img> एलिमेंट का पता लगाता है. यह तब भी होता है, जब रेंडरिंग और दस्तावेज़ को पार्स करने की सुविधा ब्लॉक हो. इस ऑप्टिमाइज़ेशन के बिना, ब्राउज़र ब्लॉकिंग की अवधि के दौरान, मौके के हिसाब से चीज़ें फ़ेच नहीं कर सकता. साथ ही, ज़्यादा संसाधनों के अनुरोध एक साथ के बजाय, लगातार किए जाएंगे.

अब आइए, असल दुनिया के कुछ पैटर्न पर नज़र डालें जिनसे प्रीलोड स्कैनर को गच्चा दिया जा सकता है. साथ ही, इन पैटर्न को ठीक करने के तरीकों के बारे में जानें.

इंजेक्ट की गई async स्क्रिप्ट

मान लें कि आपके <head> में एचटीएमएल है, जिसमें इस तरह का इनलाइन JavaScript शामिल है:

<script>
  const scriptEl = document.createElement('script');
  scriptEl.src = '/yall.min.js';

  document.head.appendChild(scriptEl);
</script>

इंजेक्ट की गई स्क्रिप्ट डिफ़ॉल्ट रूप से async होती हैं. इसलिए, जब इस स्क्रिप्ट को इंजेक्ट किया जाएगा, तो यह वैसे ही काम करेगी जैसे उस पर async एट्रिब्यूट लागू किया गया हो. इसका मतलब है कि यह जल्द से जल्द चलेगा और रेंडरिंग को ब्लॉक नहीं करेगा. यह सही लगता है, है न? हालांकि, अगर आपने यह मान लिया है कि यह इनलाइन <script>, बाहरी सीएसएस फ़ाइल को लोड करने वाले <link> एलिमेंट के बाद आता है, तो आपको खराब नतीजा मिलेगा:

इस WebPageTest चार्ट में दिखाया गया है कि स्क्रिप्ट इंजेक्ट होने पर, प्रीलोड स्कैन की प्रोसेस कैसे खराब हो जाती है.
इमेज 5: किसी वेब पेज का WebPageTest नेटवर्क वॉटरफ़ॉल चार्ट, जो किसी मोबाइल डिवाइस पर Chrome पर चलाया गया है. यह सिम्युलेट किए गए 3G कनेक्शन पर चलाया गया है. इस पेज में एक स्टाइलशीट और इंजेक्ट की गई async स्क्रिप्ट है. प्रीलोड स्कैनर, रेंडर ब्लॉकिंग फ़ेज़ के दौरान स्क्रिप्ट का पता नहीं लगा सकता, क्योंकि इसे क्लाइंट पर इंजेक्ट किया जाता है.

आइए, देखते हैं कि यहां क्या हुआ:

  1. 0 सेकंड पर, मुख्य दस्तावेज़ का अनुरोध किया जाता है.
  2. 1.4 सेकंड में, नेविगेशन अनुरोध का पहला बाइट मिलता है.
  3. दो सेकंड के बाद, सीएसएस और इमेज का अनुरोध किया जाता है.
  4. पार्सर, स्टाइलशीट को लोड करने से ब्लॉक हो जाता है. साथ ही, async स्क्रिप्ट को इंजेक्ट करने वाला इनलाइन JavaScript, स्टाइलशीट के बाद 2.6 सेकंड में आता है. इसलिए, स्क्रिप्ट से मिलने वाली सुविधा, जल्द से जल्द उपलब्ध नहीं होती.

यह तरीका बेहतर नहीं है, क्योंकि स्क्रिप्ट का अनुरोध सिर्फ़ स्टाइलशीट के डाउनलोड होने के बाद किया जाता है. इससे स्क्रिप्ट को जल्द से जल्द चलने में देरी होती है. इसके उलट, सर्वर से मिले मार्कअप में <img> एलिमेंट को खोजा जा सकता है. इसलिए, उसे प्रीलोड स्कैनर से खोजा जाता है.

इसलिए, अगर डीओएम में स्क्रिप्ट इंजेक्ट करने के बजाय, async एट्रिब्यूट के साथ किसी सामान्य <script> टैग का इस्तेमाल किया जाता है, तो क्या होगा?

<script src="/yall.min.js" async></script>

इसका नतीजा यह हुआ:

WebPageTest नेटवर्क वॉटरफ़ॉल, जिसमें दिखाया गया है कि एचटीएमएल स्क्रिप्ट एलिमेंट का इस्तेमाल करके लोड की गई असाइन स्क्रिप्ट, ब्राउज़र के प्रीलोड स्कैनर से अब भी खोजी जा सकती है. भले ही, स्टाइलशीट को डाउनलोड और प्रोसेस करते समय ब्राउज़र का प्राइमरी एचटीएमएल पार्सर ब्लॉक हो.
छठा चित्र: सिम्युलेट किए गए 3G कनेक्शन पर, मोबाइल डिवाइस पर Chrome पर चलाए जा रहे वेब पेज का WebPageTest नेटवर्क वॉटरफ़ॉल चार्ट. पेज में एक स्टाइलशीट और एक async <script> एलिमेंट है. प्रीलोड स्कैनर, रेंडर ब्लॉकिंग फ़ेज़ के दौरान स्क्रिप्ट का पता लगाता है और उसे सीएसएस के साथ लोड करता है.

ऐसा हो सकता है कि आपको यह सुझाव देने का मन करे कि rel=preload का इस्तेमाल करके इन समस्याओं को ठीक किया जा सकता है. यह तरीका काम करेगा, लेकिन इसके कुछ दुष्प्रभाव हो सकते हैं. आखिर, ऐसी समस्या को ठीक करने के लिए rel=preload का इस्तेमाल क्यों करना चाहिए जिसे डीओएम में <script> एलिमेंट को इंजेक्ट न करके रोका जा सकता है?

WebPageTest वॉटरफ़ॉल, जिसमें दिखाया गया है कि rel=preload रिसॉर्स हिंट का इस्तेमाल, असाइनिक इंजेक्ट की गई स्क्रिप्ट की खोज को बढ़ावा देने के लिए कैसे किया जाता है. हालांकि, ऐसा इस तरह किया जाता है कि अनचाहे साइड इफ़ेक्ट हो सकते हैं.
इमेज 7: वेब पेज का WebPageTest नेटवर्क वॉटरफ़ॉल चार्ट, जो किसी मोबाइल डिवाइस पर Chrome में, सिम्युलेट किए गए 3G कनेक्शन पर चलाया गया है. पेज में एक स्टाइलशीट और इंजेक्ट की गई 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 के डाउनलोड, कंपाइल, और लागू होने तक इमेज लोड नहीं होती.

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

इमेज का साइज़, व्यूपोर्ट के साइज़ पर निर्भर करता है. इस आधार पर, इमेज को सबसे बड़े कॉन्टेंटफ़ुल पेंट (एलसीपी) के लिए चुना जा सकता है. जब प्रीलोड स्कैनर, अनुमान के आधार पर इमेज रिसॉर्स को पहले से फ़ेच नहीं कर पाता है, तो एलसीपी पर असर पड़ता है. ऐसा तब हो सकता है, जब पेज की स्टाइलशीट रेंडरिंग को ब्लॉक कर रही हों.

इसका हल, इमेज मार्कअप बदलना है:

<img src="/sand-wasp.jpg" alt="Sand Wasp" width="384" height="255">

यह स्टार्टअप के दौरान व्यूपोर्ट में मौजूद इमेज के लिए सबसे सही पैटर्न है. ऐसा इसलिए, क्योंकि प्रीलोड स्कैनर, इमेज रिसॉर्स को ज़्यादा तेज़ी से खोजेगा और फ़ेच करेगा.

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

इस आसान उदाहरण में, धीमे कनेक्शन पर एलसीपी में 100 मिलीसेकंड का सुधार हुआ है. ऐसा हो सकता है कि आपको यह बहुत बड़ा सुधार न लगे. हालांकि, यह तब बड़ा सुधार लगता है, जब यह माना जाए कि यह समाधान, मार्कअप को तुरंत ठीक करने का तरीका है. साथ ही, ज़्यादातर वेब पेज, इन उदाहरणों के सेट से ज़्यादा जटिल होते हैं. इसका मतलब है कि एलसीपी कैंडिडेट को कई अन्य संसाधनों के साथ बैंडविड्थ के लिए संघर्ष करना पड़ सकता है. इसलिए, इस तरह के ऑप्टिमाइज़ेशन ज़्यादा से ज़्यादा अहम हो जाते हैं.

सीएसएस बैकग्राउंड इमेज

याद रखें कि ब्राउज़र प्रीलोड स्कैनर, मार्कअप को स्कैन करता है. यह सीएसएस जैसे अन्य रिसॉर्स टाइप को स्कैन नहीं करता. इसमें background-image प्रॉपर्टी से रेफ़र की गई इमेज को फ़ेच करना शामिल हो सकता है.

एचटीएमएल की तरह ही, ब्राउज़र सीएसएस को अपने ऑब्जेक्ट मॉडल में प्रोसेस करते हैं. इसे CSSOM कहा जाता है. अगर सीएसएसओएम बनाते समय बाहरी रिसॉर्स मिलते हैं, तो उन रिसॉर्स के लिए अनुरोध, खोजने के समय किया जाता है, न कि प्रीलोड स्कैनर से.

मान लें कि आपके पेज का एलसीपी कैंडिडेट, सीएसएस background-image प्रॉपर्टी वाला एलिमेंट है. संसाधन लोड होने पर, ये काम होते हैं:

WebPageTest नेटवर्क वॉटरफ़ॉल चार्ट, जिसमें background-image प्रॉपर्टी का इस्तेमाल करके सीएसएस से लोड किए गए एलसीपी कैंडिडेट वाले पेज को दिखाया गया है. एलसीपी के लिए चुनी गई इमेज, ऐसे रिसॉर्स टाइप में है जिसकी जांच ब्राउज़र प्रीलोड स्कैनर नहीं कर सकता. इसलिए, सीएसएस डाउनलोड और प्रोसेस होने तक रिसॉर्स लोड होने में देरी होती है. इससे एलसीपी के लिए चुनी गई इमेज के पेंट होने में देरी होती है.
इमेज 10: वेब पेज का WebPageTest नेटवर्क वॉटरफ़ॉल चार्ट, जो किसी मोबाइल डिवाइस पर Chrome पर चलाया गया है. यह सिम्युलेट किए गए 3G कनेक्शन पर चलाया गया है. पेज का एलसीपी कैंडिडेट, सीएसएस 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 हिंट छोटा है, लेकिन इससे ब्राउज़र को इमेज को जल्दी खोजने में मदद मिलती है:

WebPageTest नेटवर्क वॉटरफ़ॉल चार्ट, जिसमें rel=preload हिंट का इस्तेमाल करने की वजह से, सीएसएस बैकग्राउंड इमेज (जो एलसीपी कैंडिडेट है) बहुत जल्दी लोड हो रही है. एलसीपी का समय करीब 250 मिलीसेकंड तक बेहतर हो जाता है.
इमेज 11: किसी वेब पेज का WebPageTest नेटवर्क वॉटरफ़ॉल चार्ट, जो किसी मोबाइल डिवाइस पर Chrome पर चलाया गया है. यह सिम्युलेट किए गए 3G कनेक्शन पर चलाया गया है. पेज का एलसीपी कैंडिडेट, सीएसएस background-image प्रॉपर्टी (तीसरी लाइन) वाला एलिमेंट है. rel=preload हिंट की मदद से, ब्राउज़र को इमेज को ढूंढने में, बिना हिंट के ढूंढने में लगने वाले समय से करीब 250 मिलीसेकंड कम समय लगता है.

rel=preload हिंट की मदद से, एलसीपी उम्मीदवार को जल्दी ढूंढा जाता है. इससे एलसीपी का समय कम हो जाता है. इस हिंट से इस समस्या को ठीक करने में मदद मिलती है. हालांकि, बेहतर विकल्प यह आकलन करना है कि आपकी इमेज एलसीपी कैंडिडेट को सीएसएस से लोड करना ज़रूरी है या नहीं. <img> टैग की मदद से, आपके पास व्यूपोर्ट के हिसाब से इमेज लोड करने पर ज़्यादा कंट्रोल होगा. साथ ही, प्रीलोड स्कैनर को इमेज ढूंढने की अनुमति भी दी जा सकेगी.

बहुत ज़्यादा रिसॉर्स इनलाइन करना

इनलाइन करने का मतलब है, किसी रिसॉर्स को एचटीएमएल में डालना. Base64 एन्कोडिंग का इस्तेमाल करके, <style> एलिमेंट में स्टाइलशीट, <script> एलिमेंट में स्क्रिप्ट, और किसी भी अन्य संसाधन को इनलाइन किया जा सकता है.

संसाधनों को डाउनलोड करने के बजाय, उन्हें इनलाइन करना ज़्यादा तेज़ हो सकता है. इसकी वजह यह है कि संसाधन के लिए अलग से अनुरोध नहीं किया जाता. यह दस्तावेज़ में दिखता है और तुरंत लोड होता है. हालांकि, इसमें कुछ समस्याएं हैं:

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

उदाहरण के लिए, यह पेज देखें. कुछ मामलों में, पेज पर सबसे ऊपर मौजूद इमेज, एलसीपी कैंडिडेट होती है. साथ ही, सीएसएस किसी <link> एलिमेंट से लोड की गई अलग फ़ाइल में होती है. इस पेज पर चार वेब फ़ॉन्ट का भी इस्तेमाल किया गया है. इन फ़ॉन्ट के लिए, सीएसएस संसाधन से अलग फ़ाइलों के तौर पर अनुरोध किया गया है.

WebPageTest का नेटवर्क वॉटरफ़ॉल चार्ट, जिसमें पेज के लिए इस्तेमाल की गई बाहरी सीएसएस फ़ाइल है. इसमें चार फ़ॉन्ट का रेफ़रंस दिया गया है. प्रीलोड स्कैनर, समय के साथ एलसीपी की संभावित इमेज का पता लगा लेता है.
इमेज 12: किसी वेब पेज का WebPageTest नेटवर्क वॉटरफ़ॉल चार्ट, जो किसी मोबाइल डिवाइस पर Chrome पर चलाया गया है. यह सिम्युलेट किए गए 3G कनेक्शन पर चलाया गया है. पेज का एलसीपी कैंडिडेट, <img> एलिमेंट से लोड की गई इमेज है. हालांकि, इसे प्रीलोड स्कैनर से खोजा जाता है, क्योंकि पेज के लिए ज़रूरी सीएसएस और फ़ॉन्ट अलग-अलग रिसॉर्स में लोड होते हैं. इससे प्रीलोड स्कैनर को अपना काम करने में देरी नहीं होती.

अब अगर सीएसएस और सभी फ़ॉन्ट को बेस64 रिसॉर्स के तौर पर इनलाइन किया जाता है, तो क्या होगा?

WebPageTest का नेटवर्क वॉटरफ़ॉल चार्ट, जिसमें पेज के लिए इस्तेमाल की गई बाहरी सीएसएस फ़ाइल है. इसमें चार फ़ॉन्ट का रेफ़रंस दिया गया है. प्रीलोड स्कैनर को एलसीपी इमेज ढूंढने में काफ़ी समय लगता है .
इमेज 13: 3G कनेक्शन की नकल करके, मोबाइल डिवाइस पर Chrome पर चलाए जा रहे वेब पेज का WebPageTest नेटवर्क वॉटरफ़ॉल चार्ट. पेज का एलसीपी उम्मीदवार, <img> एलिमेंट से लोड की गई इमेज है. हालांकि, " में सीएसएस और उसके चार फ़ॉन्ट रिसॉर्स को इनलाइन करने से, प्रीलोड स्कैनर को इमेज को तब तक खोजने में देरी होती है, जब तक वे रिसॉर्स पूरी तरह से डाउनलोड नहीं हो जाते.

इस उदाहरण में, इनलाइन करने से एलसीपी और परफ़ॉर्मेंस पर बुरा असर पड़ता है. पेज का वह वर्शन जो कुछ भी इनलाइन नहीं करता है, वह एलसीपी इमेज को करीब 3.5 सेकंड में पेंट करता है. जो पेज सभी चीज़ों को इनलाइन करता है वह एलसीपी इमेज को सात सेकंड से ज़्यादा समय तक पेंट नहीं करता.

यहां प्रीलोड स्कैनर के अलावा और भी चीज़ें काम करती हैं. फ़ॉन्ट को इनलाइन करना एक अच्छी रणनीति नहीं है, क्योंकि base64, बाइनरी संसाधनों के लिए एक खराब फ़ॉर्मैट है. एक और बात यह है कि बाहरी फ़ॉन्ट संसाधन तब तक डाउनलोड नहीं किए जाते, जब तक कि CSSOM उन्हें ज़रूरी न समझे. जब उन फ़ॉन्ट को base64 के तौर पर इनलाइन किया जाता है, तो उन्हें डाउनलोड कर लिया जाता है. भले ही, वे मौजूदा पेज के लिए ज़रूरी हों या नहीं.

क्या प्रीलोड करने से इस समस्या को ठीक किया जा सकता है? बेशक। एलसीपी इमेज को प्रीलोड करके, एलसीपी का समय कम किया जा सकता है. हालांकि, इनलाइन किए गए संसाधनों की वजह से, कैश मेमोरी में सेव नहीं किए जा सकने वाले एचटीएमएल का साइज़ बढ़ जाता है. इससे परफ़ॉर्मेंस पर बुरा असर पड़ता है. इस पैटर्न का असर फ़र्स्ट कॉन्टेंटफ़ुल पेंट (एफ़सीपी) पर भी पड़ता है. पेज के उस वर्शन में जहां कुछ भी इनलाइन नहीं किया गया है, एफ़सीपी करीब 2.7 सेकंड है. जिस वर्शन में सब कुछ इनलाइन किया गया है उसमें एफ़सीपी करीब 5.8 सेकंड है.

एचटीएमएल में कॉन्टेंट को इनलाइन करते समय बहुत सावधानी बरतें. खास तौर पर, base64 में एन्कोड किए गए संसाधनों को इनलाइन करते समय. आम तौर पर, इसका सुझाव नहीं दिया जाता. हालांकि, बहुत छोटे संसाधनों के लिए ऐसा किया जा सकता है. ज़्यादा से ज़्यादा इनलाइन करें, क्योंकि बहुत ज़्यादा इनलाइन करने से समस्याएं हो सकती हैं.

क्लाइंट-साइड JavaScript की मदद से मार्कअप रेंडर करना

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

क्लाइंट-साइड JavaScript की मदद से मार्कअप को रेंडर करने से, प्रीलोड स्कैनर को गच्चा दिया जा सकता है:

WebPageTest नेटवर्क वॉटरफ़ॉल, जिसमें JavaScript में क्लाइंट पर पूरी तरह से रेंडर की गई इमेज और टेक्स्ट वाला बुनियादी पेज दिखाया गया है. मार्कअप, JavaScript में मौजूद होता है. इसलिए, प्रीलोड स्कैनर किसी भी रिसॉर्स का पता नहीं लगा सकता. JavaScript फ़्रेमवर्क के लिए, नेटवर्क और प्रोसेसिंग में ज़्यादा समय लगता है. इस वजह से, सभी संसाधनों को लोड होने में भी ज़्यादा समय लगता है.
इमेज 14: क्लाइंट-रेंडर किए गए वेब पेज का WebPageTest नेटवर्क वॉटरफ़ॉल चार्ट. यह पेज, सिम्युलेट किए गए 3G कनेक्शन पर मोबाइल डिवाइस में Chrome पर चलता है. कॉन्टेंट, JavaScript में होता है और उसे रेंडर करने के लिए फ़्रेमवर्क का इस्तेमाल किया जाता है. इसलिए, क्लाइंट-रेंडर किए गए मार्कअप में मौजूद इमेज रिसॉर्स, प्रीलोड स्कैनर से छिपा होता है. सर्वर से रेंडर किए गए पेज का उदाहरण चित्र 9 में दिया गया है.

जब मार्कअप पेलोड, ब्राउज़र में JavaScript में शामिल होते हैं और पूरी तरह से रेंडर किए जाते हैं, तो उस मार्कअप में मौजूद किसी भी संसाधन को प्रीलोड स्कैनर नहीं देख पाता. इससे ज़रूरी रिसॉर्स ढूंढने में देरी होती है, जिसका असर एलसीपी पर पड़ता है. इन उदाहरणों के मामले में, सर्वर से रेंडर किए गए उस वर्शन की तुलना में, LCP इमेज के अनुरोध में काफ़ी देरी होती है जिसमें JavaScript की ज़रूरत नहीं होती.

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

इस स्थिति को ठीक करने का तरीका, इस सवाल के जवाब पर निर्भर करता है: क्या कोई ऐसी वजह है जिसकी वजह से आपके पेज का मार्कअप, क्लाइंट पर रेंडर होने के बजाय सर्वर से नहीं दिया जा सकता? अगर इसका जवाब "नहीं" है, तो जहां भी हो सके वहां सर्वर-साइड रेंडरिंग (एसएसआर) या स्टैटिक तौर पर जनरेट किए गए मार्कअप का इस्तेमाल किया जाना चाहिए. इससे, प्रीलोड स्कैनर को समय से पहले ज़रूरी संसाधनों को खोजने और फ़ेच करने में मदद मिलेगी.

अगर आपके पेज के मार्कअप के कुछ हिस्सों में फ़ंक्शन जोड़ने के लिए, आपके पेज को JavaScript की ज़रूरत है, तो एसएसआर की मदद से ऐसा किया जा सकता है. इसके लिए, वैनिला JavaScript या हाइड्रेशन का इस्तेमाल किया जा सकता है. इससे, दोनों तरीकों का फ़ायदा मिलता है.

प्रीलोड स्कैनर की मदद पाना

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

आपको याद दिला दें कि इस पोस्ट में ये बातें बताई गई हैं:

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

अगर किसी भी वजह से, आपको ऐसे पैटर्न से बचने में समस्या आ रही है जिससे पेज लोड होने की परफ़ॉर्मेंस को तेज़ करने के लिए, प्रीलोड स्कैनर की क्षमता पर बुरा असर पड़ता है, तो rel=preload रिसॉर्स के लिए दिए गए सुझाव पर विचार करें. अगर rel=preload का इस्तेमाल किया जाता है, तो लैब टूल में जांच करें. इससे यह पक्का किया जा सकेगा कि आपको मनमुताबिक नतीजा मिल रहा है या नहीं. आखिर में, बहुत ज़्यादा संसाधनों को प्रीलोड न करें. ऐसा करने पर, किसी भी संसाधन को प्राथमिकता नहीं दी जा सकेगी.

संसाधन

Unsplash से ली गई हीरो इमेज, जिसे मोहम्मद रहमानी ने बनाया है .