पिछले मॉड्यूल में, क्रिटिकल रेंडरिंग पाथ के पीछे की कुछ थ्योरी के बारे में बताया गया था. साथ ही, यह भी बताया गया था कि रेंडरिंग और पार्सर को ब्लॉक करने वाले संसाधन, पेज की शुरुआती रेंडरिंग में कैसे देरी कर सकते हैं. अब आपको इस बारे में कुछ बुनियादी जानकारी मिल गई है. इसलिए, अब आपके पास क्रिटिकल रेंडरिंग पाथ को ऑप्टिमाइज़ करने की कुछ तकनीकों के बारे में जानने का विकल्प है.
जब कोई पेज लोड होता है, तो उसके एचटीएमएल में कई रिसॉर्स के रेफ़रंस दिए जाते हैं. ये रिसॉर्स, पेज को सीएसएस के ज़रिए उसका लुक और लेआउट देते हैं. साथ ही, JavaScript के ज़रिए उसे इंटरैक्टिव बनाते हैं. इस मॉड्यूल में, इन संसाधनों से जुड़े कई अहम कॉन्सेप्ट के बारे में बताया गया है. साथ ही, यह भी बताया गया है कि ये किसी पेज के लोड होने में लगने वाले समय पर कैसे असर डालते हैं.
रेंडर होने से रोका जा रहा है
पिछले मॉड्यूल में बताया गया था कि सीएसएस एक रेंडर रोकने वाला रिसॉर्स है. ऐसा इसलिए, क्योंकि यह ब्राउज़र को तब तक कोई भी कॉन्टेंट रेंडर करने से रोकता है, जब तक कि सीएसएस ऑब्जेक्ट मॉडल (सीएसएसओएम) नहीं बन जाता. ब्राउज़र, रेंडरिंग को ब्लॉक कर देता है, ताकि बिना स्टाइल वाले कॉन्टेंट का फ़्लैश (एफ़ओयूसी) न हो. उपयोगकर्ता अनुभव के लिहाज़ से, यह सही नहीं है.
ऊपर दिए गए वीडियो में, कुछ समय के लिए FOUC दिखता है. इसमें पेज बिना किसी स्टाइल के दिखता है. इसके बाद, पेज की सीएसएस के नेटवर्क से लोड होने के बाद, सभी स्टाइल लागू हो जाती हैं. साथ ही, स्टाइल नहीं किए गए पेज को तुरंत स्टाइल किए गए पेज से बदल दिया जाता है.
आम तौर पर, आपको FOUC नहीं दिखता. हालांकि, इस कॉन्सेप्ट को समझना ज़रूरी है, ताकि आपको पता चल सके कि ब्राउज़र, सीएसएस डाउनलोड होने और पेज पर लागू होने तक पेज को रेंडर करने से क्यों रोकता है. रेंडरिंग को ब्लॉक करना ज़रूरी नहीं कि खराब हो. हालांकि, आपको यह पक्का करना चाहिए कि यह कम से कम समय तक हो. इसके लिए, अपनी सीएसएस को ऑप्टिमाइज़ करें.
पार्सर ब्लॉकिंग
पार्सर-ब्लॉकिंग संसाधन, एचटीएमएल पार्सर में रुकावट डालता है. जैसे, async या defer एट्रिब्यूट के बिना <script> एलिमेंट. जब पार्सर को <script> एलिमेंट मिलता है, तो ब्राउज़र को स्क्रिप्ट का आकलन करना होता है और उसे लागू करना होता है. इसके बाद ही, वह बाकी एचटीएमएल को पार्स कर पाता है. ऐसा इसलिए होता है, क्योंकि स्क्रिप्ट, डीओएम को बनाते समय उसमें बदलाव कर सकती हैं या उसे ऐक्सेस कर सकती हैं.
<!-- This is a parser-blocking script: -->
<script src="/script.js"></script>
बाहरी JavaScript फ़ाइलों का इस्तेमाल करते समय (async या defer के बिना— या type=module, जो डिफ़ॉल्ट रूप से defer होता है), फ़ाइल का पता चलने से लेकर उसके डाउनलोड, पार्स, और एक्ज़ीक्यूट होने तक पार्सर ब्लॉक हो जाता है. इनलाइन JavaScript का इस्तेमाल करने पर, पार्सर को तब तक ब्लॉक कर दिया जाता है, जब तक इनलाइन स्क्रिप्ट को पार्स और एक्ज़ीक्यूट नहीं कर लिया जाता.
प्रीलोड स्कैनर
प्रीलोड स्कैनर, ब्राउज़र को ऑप्टिमाइज़ करने की सुविधा है. यह एक सेकंडरी एचटीएमएल पार्सर के तौर पर काम करता है. यह एचटीएमएल रिस्पॉन्स को स्कैन करता है, ताकि मुख्य एचटीएमएल पार्सर के उन्हें ढूंढने से पहले ही संसाधनों को खोजा जा सके और उन्हें फ़ेच किया जा सके. उदाहरण के लिए, प्रीलोड स्कैनर, ब्राउज़र को <img> एलिमेंट में बताए गए रिसॉर्स को डाउनलोड करना शुरू करने की अनुमति देगा. ऐसा तब भी होगा, जब सीएसएस और JavaScript जैसे रिसॉर्स को फ़ेच और प्रोसेस करते समय एचटीएमएल पार्सर ब्लॉक हो जाता है.
प्रीलोड स्कैनर का फ़ायदा पाने के लिए, ज़रूरी संसाधनों को सर्वर से भेजे गए एचटीएमएल मार्कअप में शामिल किया जाना चाहिए. प्रीलोड स्कैनर, संसाधन लोड करने के इन पैटर्न का पता नहीं लगा सकता:
background-imageप्रॉपर्टी का इस्तेमाल करके, सीएसएस से लोड की गई इमेज. ये इमेज रेफ़रंस, सीएसएस में हैं. इसलिए, प्रीलोड स्कैनर इन्हें ढूंढ नहीं सकता.- डाइनैमिक रूप से लोड की गई स्क्रिप्ट,
<script>एलिमेंट मार्कअप के तौर पर इंजेक्ट की जाती हैं. इन्हें JavaScript का इस्तेमाल करके DOM में इंजेक्ट किया जाता है. इसके अलावा, इन्हें डाइनैमिकimport()का इस्तेमाल करके लोड किए गए मॉड्यूल के तौर पर भी इंजेक्ट किया जाता है. - JavaScript का इस्तेमाल करके, क्लाइंट पर रेंडर किया गया एचटीएमएल. इस तरह का मार्कअप, JavaScript संसाधनों में मौजूद स्ट्रिंग में शामिल होता है. साथ ही, प्रीलोड स्कैनर इसे ढूंढ नहीं पाता.
- सीएसएस
@importएलान.
ये सभी संसाधन लोडिंग पैटर्न, देर से खोजे गए संसाधन हैं. इसलिए, इन्हें प्रीलोड स्कैनर का फ़ायदा नहीं मिलता. जब भी हो सके, इनसे बचें. अगर इस तरह के पैटर्न से बचना मुमकिन नहीं है, तो संसाधन खोजने में होने वाली देरी से बचने के लिए, preload हिंट का इस्तेमाल किया जा सकता है.
सीएसएस
सीएसएस से, किसी पेज का लेआउट और प्रज़ेंटेशन तय होता है. जैसा कि पहले बताया गया है, सीएसएस एक रेंडर रोकने वाला रिसॉर्स है. इसलिए, सीएसएस को ऑप्टिमाइज़ करने से, पेज लोड होने के कुल समय पर काफ़ी असर पड़ सकता है.
काट-छांट
सीएसएस फ़ाइलों को छोटा करने से, सीएसएस रिसॉर्स का फ़ाइल साइज़ कम हो जाता है. इससे उन्हें तेज़ी से डाउनलोड किया जा सकता है. यह काम मुख्य रूप से, सोर्स सीएसएस फ़ाइल से कॉन्टेंट हटाकर किया जाता है. जैसे, स्पेस और अन्य अदृश्य वर्ण. इसके बाद, नतीजे को नई ऑप्टिमाइज़ की गई फ़ाइल में आउटपुट किया जाता है:
/* Unminified CSS: */
/* Heading 1 */
h1 {
font-size: 2em;
color: #000000;
}
/* Heading 2 */
h2 {
font-size: 1.5em;
color: #000000;
}
/* Minified CSS: */
h1,h2{color:#000}h1{font-size:2em}h2{font-size:1.5em}
सीएसएस को छोटा करना, ऑप्टिमाइज़ेशन का एक असरदार तरीका है. इससे आपकी वेबसाइट के FCP को बेहतर बनाया जा सकता है. साथ ही, कुछ मामलों में LCP को भी बेहतर बनाया जा सकता है. बंडलर जैसे टूल, प्रोडक्शन बिल्ड में आपके लिए इस ऑप्टिमाइज़ेशन को अपने-आप पूरा कर सकते हैं.
इस्तेमाल नहीं किए गए सीएसएस को हटाना
किसी भी कॉन्टेंट को रेंडर करने से पहले, ब्राउज़र को सभी स्टाइल शीट डाउनलोड और पार्स करनी होती हैं. पार्सिंग में लगने वाले समय में, ऐसी स्टाइल भी शामिल होती हैं जिनका इस्तेमाल मौजूदा पेज पर नहीं किया जाता. अगर किसी बंडलर का इस्तेमाल किया जा रहा है, जो सभी सीएसएस संसाधनों को एक ही फ़ाइल में जोड़ता है, तो हो सकता है कि आपके उपयोगकर्ता, मौजूदा पेज को रेंडर करने के लिए ज़रूरत से ज़्यादा सीएसएस डाउनलोड कर रहे हों.
मौजूदा पेज के लिए इस्तेमाल न की गई सीएसएस का पता लगाने के लिए, Chrome DevTools में कवरेज टूल का इस्तेमाल करें.
इस्तेमाल न होने वाले सीएसएस को हटाने से दो फ़ायदे मिलते हैं: इससे डाउनलोड होने में लगने वाला समय कम हो जाता है. साथ ही, रेंडर ट्री को ऑप्टिमाइज़ किया जा सकता है, क्योंकि ब्राउज़र को कम सीएसएस नियमों को प्रोसेस करना पड़ता है.
सीएसएस @import एलान से बचें
सीएसएस में @import के बारे में जानकारी देने के लिए, यहां दिए गए तरीके इस्तेमाल न करें. हालांकि, ऐसा करना आसान हो सकता है:
/* Don't do this: */
@import url('style.css');
<link> एलिमेंट, एचटीएमएल में जिस तरह से काम करता है उसी तरह @import डिक्लेरेशन, सीएसएस में काम करता है. इसकी मदद से, स्टाइल शीट में बाहरी सीएसएस रिसॉर्स इंपोर्ट किया जा सकता है. इन दोनों तरीकों में मुख्य अंतर यह है कि एचटीएमएल <link> एलिमेंट, एचटीएमएल रिस्पॉन्स का हिस्सा होता है. इसलिए, इसे सीएसएस फ़ाइल के मुकाबले बहुत पहले खोज लिया जाता है. सीएसएस फ़ाइल को @import डिक्लेरेशन से डाउनलोड किया जाता है.
ऐसा इसलिए होता है, क्योंकि @import एलान का पता लगाने के लिए, उसे शामिल करने वाली सीएसएस फ़ाइल को पहले डाउनलोड किया जाना चाहिए. इस वजह से, अनुरोध चेन बनती है. सीएसएस के मामले में, इससे पेज को शुरुआती तौर पर रेंडर होने में देरी होती है. इसकी एक और कमी यह है कि @import डिक्लेरेशन का इस्तेमाल करके लोड की गई स्टाइल शीट को प्रीलोड स्कैनर नहीं ढूंढ सकता. इसलिए, ये रेंडरिंग को ब्लॉक करने वाले ऐसे संसाधन बन जाते हैं जिन्हें बाद में खोजा जाता है.
<!-- Do this instead: -->
<link rel="stylesheet" href="style.css">
ज़्यादातर मामलों में, <link rel="stylesheet"> को <link rel="stylesheet"> एलिमेंट का इस्तेमाल करके बदला जा सकता है.@import <link> एलिमेंट की मदद से, स्टाइल शीट को एक साथ डाउनलोड किया जा सकता है. इससे लोड होने में लगने वाला कुल समय कम हो जाता है. वहीं, @import डिक्लेरेशन की मदद से, स्टाइल शीट को एक के बाद एक डाउनलोड किया जाता है.
इनलाइन क्रिटिकल सीएसएस
सीएसएस फ़ाइलों को डाउनलोड होने में लगने वाले समय की वजह से, किसी पेज का एफ़सीपी बढ़ सकता है. दस्तावेज़ में ज़रूरी स्टाइल को इनलाइन करने से, <head> सीएसएस रिसॉर्स के लिए नेटवर्क अनुरोध नहीं करना पड़ता. साथ ही, सही तरीके से इनलाइन करने पर, जब उपयोगकर्ता के ब्राउज़र की कैश मेमोरी तैयार नहीं होती है, तब शुरुआती लोड समय को बेहतर बनाया जा सकता है. बची हुई सीएसएस को एसिंक्रोनस तरीके से लोड किया जा सकता है या <body> एलिमेंट के आखिर में जोड़ा जा सकता है.
<head>
<title>Page Title</title>
<!-- ... -->
<style>h1,h2{color:#000}h1{font-size:2em}h2{font-size:1.5em}</style>
</head>
<body>
<!-- Other page markup... -->
<link rel="stylesheet" href="non-critical.css">
</body>
हालांकि, ज़्यादा सीएसएस को इनलाइन करने से, शुरुआती एचटीएमएल रिस्पॉन्स में ज़्यादा बाइट जुड़ जाती हैं. एचटीएमएल रिसॉर्स को अक्सर लंबे समय तक कैश मेमोरी में सेव नहीं किया जा सकता. इसका मतलब है कि इनलाइन की गई सीएसएस को उन पेजों के लिए कैश मेमोरी में सेव नहीं किया जाता जो बाहरी स्टाइल शीट में एक ही सीएसएस का इस्तेमाल कर सकते हैं. अपने पेज की परफ़ॉर्मेंस को टेस्ट करें और उसका आकलन करें. इससे यह पक्का किया जा सकेगा कि परफ़ॉर्मेंस में सुधार करने के लिए किए गए बदलाव, फ़ायदेमंद हैं या नहीं.
सीएसएस डेमो
JavaScript
वेब पर ज़्यादातर इंटरैक्टिविटी, JavaScript की वजह से होती है. हालांकि, इसके लिए आपको कुछ कीमत चुकानी पड़ती है. बहुत ज़्यादा JavaScript का इस्तेमाल करने से, पेज लोड होने के दौरान आपका वेब पेज धीरे-धीरे जवाब देता है. इससे रिस्पॉन्सिवनेस से जुड़ी समस्याएं भी हो सकती हैं, जिससे इंटरैक्शन धीमे हो जाते हैं. ये दोनों समस्याएं उपयोगकर्ताओं के लिए परेशानी पैदा कर सकती हैं.
रेंडरिंग को ब्लॉक करने वाली JavaScript
defer या async एट्रिब्यूट के बिना <script> एलिमेंट लोड करने पर, ब्राउज़र पार्सिंग और रेंडरिंग को तब तक ब्लॉक कर देता है, जब तक स्क्रिप्ट डाउनलोड, पार्स, और एक्ज़ीक्यूट नहीं हो जाती. इसी तरह, इनलाइन स्क्रिप्ट, पार्सर को तब तक ब्लॉक करती हैं, जब तक स्क्रिप्ट को पार्स नहीं किया जाता और उसे लागू नहीं किया जाता.
async बनाम defer
async और defer, बाहरी स्क्रिप्ट को लोड करने की अनुमति देते हैं. इससे एचटीएमएल पार्सर ब्लॉक नहीं होता. वहीं, type="module" वाली स्क्रिप्ट (इनलाइन स्क्रिप्ट भी शामिल हैं) अपने-आप पोस्टपोन हो जाती हैं. हालांकि, async और defer में कुछ अंतर हैं, जिन्हें समझना ज़रूरी है.
async की मदद से लोड की गई स्क्रिप्ट को डाउनलोड करने के बाद तुरंत पार्स और लागू किया जाता है. वहीं, defer की मदद से लोड की गई स्क्रिप्ट को तब लागू किया जाता है, जब एचटीएमएल दस्तावेज़ को पार्स करने की प्रोसेस पूरी हो जाती है. ऐसा ब्राउज़र के DOMContentLoaded इवेंट के साथ ही होता है.
इसके अलावा, async स्क्रिप्ट को क्रम से लागू नहीं किया जा सकता. वहीं, defer स्क्रिप्ट को उसी क्रम में लागू किया जाता है जिस क्रम में वे मार्कअप में दिखती हैं.
क्लाइंट-साइड रेंडरिंग
आम तौर पर, आपको किसी भी ज़रूरी कॉन्टेंट या पेज के एलसीपी एलिमेंट को रेंडर करने के लिए, JavaScript का इस्तेमाल नहीं करना चाहिए. इसे क्लाइंट-साइड रेंडरिंग कहा जाता है. यह एक ऐसी तकनीक है जिसका इस्तेमाल, एक पेज वाले ऐप्लिकेशन (एसपीए) में बड़े पैमाने पर किया जाता है.
JavaScript से रेंडर किया गया मार्कअप, प्रीलोड स्कैनर को बाईपास कर देता है. ऐसा इसलिए होता है, क्योंकि क्लाइंट से रेंडर किए गए मार्कअप में मौजूद संसाधन, प्रीलोड स्कैनर को नहीं मिलते. इससे एलसीपी इमेज जैसे ज़रूरी संसाधनों को डाउनलोड करने में देरी हो सकती है. ब्राउज़र, स्क्रिप्ट के एक्ज़ीक्यूट होने और DOM में एलिमेंट जोड़ने के बाद ही एलसीपी इमेज डाउनलोड करना शुरू करता है. इसलिए, स्क्रिप्ट को तब तक नहीं चलाया जा सकता, जब तक उसे खोजा, डाउनलोड, और पार्स न कर लिया जाए. इसे अहम अनुरोधों की चेन कहा जाता है. इससे बचना चाहिए.
इसके अलावा, JavaScript का इस्तेमाल करके मार्कअप रेंडर करने से, नेविगेशन के अनुरोध के जवाब में सर्वर से डाउनलोड किए गए मार्कअप की तुलना में, लंबे टास्क जनरेट होने की संभावना ज़्यादा होती है. क्लाइंट-साइड पर एचटीएमएल रेंडरिंग का ज़्यादा इस्तेमाल करने से, इंटरैक्शन में लगने वाले समय पर बुरा असर पड़ सकता है. ऐसा खास तौर पर तब होता है, जब किसी पेज का DOM बहुत बड़ा होता है. इससे JavaScript, DOM में बदलाव करते समय रेंडरिंग का काम ट्रिगर करती है.
काट-छांट
सीएसएस की तरह ही, JavaScript को छोटा करने से स्क्रिप्ट रिसॉर्स की फ़ाइल का साइज़ कम हो जाता है. इससे डाउनलोड की प्रोसेस तेज़ी से पूरी होती है. साथ ही, ब्राउज़र JavaScript को पार्स और कंपाइल करने की प्रोसेस को तेज़ी से पूरा कर पाता है.
इसके अलावा, JavaScript को छोटा करने की प्रोसेस, CSS जैसी अन्य ऐसेट को छोटा करने की प्रोसेस से एक कदम आगे है. JavaScript को छोटा करने पर, न सिर्फ़ स्पेस, टैब, और टिप्पणियों जैसी चीज़ें हटाई जाती हैं, बल्कि सोर्स JavaScript में मौजूद सिंबल को भी छोटा किया जाता है. इस प्रोसेस को कभी-कभी यूजीलिफ़िकेशन भी कहा जाता है. अंतर देखने के लिए, यहां दिया गया JavaScript सोर्स कोड इस्तेमाल करें:
// Unuglified JavaScript source code:
export function injectScript () {
const scriptElement = document.createElement('script');
scriptElement.src = '/js/scripts.js';
scriptElement.type = 'module';
document.body.appendChild(scriptElement);
}
ऊपर दिए गए JavaScript सोर्स कोड को छोटा करने पर, नतीजा इस तरह के कोड स्निपेट के तौर पर दिख सकता है:
// Uglified JavaScript production code:
export function injectScript(){const t=document.createElement("script");t.src="/js/scripts.js",t.type="module",document.body.appendChild(t)}
ऊपर दिए गए स्निपेट में, आपको दिखेगा कि सोर्स में मौजूद, लोगों के पढ़ने लायक वैरिएबल scriptElement को छोटा करके t कर दिया गया है. स्क्रिप्ट के बड़े कलेक्शन पर इसे लागू करने से, काफ़ी बचत हो सकती है. साथ ही, इससे वेबसाइट की प्रोडक्शन JavaScript की सुविधाओं पर कोई असर नहीं पड़ता.
अगर अपनी वेबसाइट के सोर्स कोड को प्रोसेस करने के लिए किसी बंडलर का इस्तेमाल किया जा रहा है, तो प्रोडक्शन बिल्ड के लिए अक्सर कोड को छोटा करने की प्रोसेस अपने-आप हो जाती है. यूजीलिफ़ायर, जैसे कि टर्सर को भी काफ़ी हद तक कॉन्फ़िगर किया जा सकता है. इससे आपको ज़्यादा से ज़्यादा बचत करने के लिए, यूजीलिफ़िकेशन एल्गोरिदम की गंभीरता में बदलाव करने की सुविधा मिलती है. हालांकि, किसी भी यूग्लिफ़िकेशन टूल के डिफ़ॉल्ट सेटिंग आम तौर पर, आउटपुट साइज़ और क्षमताओं को बनाए रखने के बीच सही संतुलन बनाने के लिए काफ़ी होती हैं.
JavaScript डेमो
अपने ज्ञान को परखें
ब्राउज़र में एक से ज़्यादा सीएसएस फ़ाइलें लोड करने का सबसे अच्छा तरीका क्या है?
@import एलान.<link> एलिमेंट.ब्राउज़र प्रीलोड स्कैनर क्या करता है?
<link rel="preload"> एलिमेंट का पता लगाती है.
JavaScript रिसॉर्स डाउनलोड करते समय, ब्राउज़र डिफ़ॉल्ट रूप से एचटीएमएल को पार्स करने पर कुछ समय के लिए रोक क्यों लगाता है?
आगे: संसाधन के बारे में जानकारी देकर ब्राउज़र की मदद करना
अब आपको पता चल गया है कि <head> एलिमेंट में लोड किए गए रिसॉर्स, पेज लोड होने में लगने वाले शुरुआती समय और अलग-अलग मेट्रिक पर कैसे असर डाल सकते हैं. अब आगे बढ़ते हैं. अगले मॉड्यूल में, संसाधन के बारे में जानकारी देने वाले निर्देशों के बारे में बताया गया है. साथ ही, यह बताया गया है कि ये निर्देश, ब्राउज़र को संसाधन लोड करने और क्रॉस-ऑरिजिन सर्वर से कनेक्शन खोलने के बारे में अहम जानकारी कैसे दे सकते हैं. इससे ब्राउज़र, इन निर्देशों के बिना ऐसा करने में जितना समय लेता है उससे पहले ही यह काम कर लेता है.