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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

यह रहा नतीजा:

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

data- प्रीफ़िक्स का इस्तेमाल, JavaScript की मदद से काम करने वाले लेज़ी लोडर में आम तौर पर किया जाता है. जब इमेज को व्यूपोर्ट में स्क्रोल किया जाता है, तो लेज़ी लोडर data- प्रीफ़िक्स हटा देता है. इसका मतलब है कि ऊपर दिए गए उदाहरण में, data-src, src बन जाता है. इस अपडेट से ब्राउज़र को संसाधन फ़ेच करने का अनुरोध मिलता है.

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

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

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

इमेज मार्कअप बदलने का तरीका:

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

प्रीलोड स्कैनर को धोखा देने वाला एक पैटर्न, क्लाइंट-साइड JavaScript की मदद से मार्कअप रेंडर करना है:

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

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

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

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

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

प्रीलोड स्कैनर की मदद से, अपनी वेबसाइट को बेहतर बनाएं

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

इस पोस्ट में बताई गई मुख्य बातें यहां दी गई हैं:

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

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

संसाधन

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