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

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

जेरेमी वैगनर
जेरेमी वैगनर

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

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

पहले से लोड किया जाने वाला स्कैनर क्या होता है?

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

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

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

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

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

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

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

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

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

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

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

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

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

आइए, इसके बारे में जानते हैं कि यहां क्या हुआ:

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

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

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

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

यह नतीजा है:

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

इस बात की संभावना बढ़ जाती है कि rel=preload का इस्तेमाल करके इन समस्याओं को ठीक किया जा सकता है. यह तरीका कारगर साबित होता है, लेकिन इसके कुछ खराब असर हो सकते हैं. ऐसा इसलिए ज़रूरी है, क्योंकि सवाल हल करने के लिए rel=preload का इस्तेमाल उस समस्या को ठीक करने के लिए क्यों करना चाहिए जिसे DOM में <script> एलिमेंट इंजेक्ट करके किया जा सकता है?

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

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

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

इसे हल करने के लिए, इमेज के मार्कअप में बदलाव करें:

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

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

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

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

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

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

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

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

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

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

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

बहुत ज़्यादा संसाधनों को इनलाइन करना

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

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

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

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

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

अब अगर सीएसएस और सभी फ़ॉन्ट को base64 संसाधन के रूप में इनलाइन किया गया है, तो क्या होगा?

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

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

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

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

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

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

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

एक पैटर्न जो प्रीलोड स्कैनर को हरा सकता है वह है क्लाइंट-साइड JavaScript के साथ मार्कअप को रेंडर करना:

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

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

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

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

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

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

पहले से लोड होने वाले स्कैनर की मदद से, आपकी मदद करें

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

आपको याद दिला दें कि आपको इस पोस्ट से ये चीज़ें हटानी होंगी:

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

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

रिसॉर्स

Unsplash की हीरो इमेज, इसे मोहम्मद रहमानी ने लिखा है.