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

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

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

ब्राउज़र प्रीलोड स्कैनर को समझने के लिए एक इंटरनल ब्राउज़र ऑप्टिमाइज़ेशन है. इस पोस्ट में बताया जाएगा कि प्रीलोड स्कैनर कैसे काम करता है—और सबसे अहम बात यह है कि इस प्रोसेस में आने से कैसे बचें.

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

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

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

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

पहले से लोड करने से समस्या "ठीक हो जाती है". हालांकि, इससे एक नई समस्या आ जाती है: पहले दो डेमो में से async स्क्रिप्ट—<head> में लोड होने के बावजूद—को "कम" प्राथमिकता पर लोड किया जाता है, जबकि स्टाइलशीट को "सबसे ज़्यादा" प्राथमिकता पर लोड किया जाता है. पिछले डेमो में जहां async स्क्रिप्ट पहले से लोड की गई थी, उसमें स्टाइलशीट अब भी "सबसे ज़्यादा" प्राथमिकता पर लोड की गई है, लेकिन स्क्रिप्ट की प्राथमिकता को "ज़्यादा" पर सेट कर दिया गया है.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

आपको याद दिला दें कि इस पोस्ट में आपको इन बातों का ध्यान रखना होगा:

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

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

संसाधन

मोहम्मद रहमानी की Unस्प्लैश की हीरो इमेज.