पिछले मॉड्यूल में, क्रिटिकल रेंडरिंग पाथ के पीछे के कुछ सिद्धांत के बारे में जाना गया. साथ ही, हमने बताया कि रेंडर-ब्लॉकिंग और पार्सर-ब्लॉक करने वाले संसाधन, किसी पेज की शुरुआती रेंडरिंग में किस तरह देरी कर सकते हैं. अब आपको इसके पीछे की वजह समझ आ गई है, तो अब आप क्रिटिकल रेंडरिंग पाथ को ऑप्टिमाइज़ करने की कुछ तकनीकें सीखने के लिए तैयार हैं.
पेज लोड होने पर, इसके एचटीएमएल में कई रिसॉर्स का रेफ़रंस दिया जाता है. ये रिसॉर्स, सीएसएस की मदद से दिखने वाले और लेआउट वाले पेज की जानकारी देते हैं. साथ ही, JavaScript की मदद से इसकी इंटरैक्टिविटी भी देते हैं. इस मॉड्यूल में, इन संसाधनों से संबंधित कई ज़रूरी कॉन्सेप्ट को शामिल किया गया है और बताया गया है कि ये पेज के लोड होने में लगने वाले समय पर कैसे असर डालती हैं.
रेंडर होने से रोकना
जैसा कि पिछले मॉड्यूल में बताया गया था, सीएसएस एक रेंडर ब्लॉक करने वाला संसाधन है, क्योंकि यह ब्राउज़र को तब तक कोई कॉन्टेंट रेंडर करने से रोकता है, जब तक सीएसएस ऑब्जेक्ट मॉडल (सीएसएसओएम) नहीं बन जाता. ब्राउज़र, अनस्टाइल कॉन्टेंट (एफ़ओयूसी) के फ़्लैश को रोकने के लिए रेंडरिंग को ब्लॉक करता है, जो उपयोगकर्ता अनुभव के हिसाब से सही नहीं है.
पिछले वीडियो में, एक छोटी सी FOUC के बारे में बताया गया है, जिसमें बिना किसी स्टाइल के पेज को देखा जा सकता है. जैसे ही पेज के सीएसएस, नेटवर्क से लोड हो जाते हैं, सभी स्टाइल लागू हो जाती हैं. साथ ही, पेज का बिना स्टाइल वाला वर्शन तुरंत स्टाइल वाले वर्शन से बदल दिया जाता है.
आम तौर पर, FOUC आपको आम तौर पर नहीं दिखता है. इस कॉन्सेप्ट को समझना ज़रूरी है, ताकि आपको पता चल सके कि जब तक सीएसएस डाउनलोड करके उसे पेज पर लागू नहीं किया जाता, तब तक ब्राउज़र पेज को रेंडर क्यों नहीं कर रहा है. अगर आपको इमेज रेंडर होने में कोई रुकावट नहीं चाहिए, तो उसे ऑप्टिमाइज़ न करें.
पार्सर ब्लॉक करना
पार्सर-ब्लॉक करने वाला रिसॉर्स, एचटीएमएल पार्सर में रुकावट डालता है, जैसे कि async
या defer
एट्रिब्यूट के बिना, <script>
एलिमेंट. जब पार्सर को कोई
<script>
एलिमेंट मिलता है, तो बाकी के एचटीएमएल को पार्स करने से पहले, ब्राउज़र को स्क्रिप्ट का आकलन करके उसे एक्ज़ीक्यूट करना होता है. ऐसा इसलिए किया जाता है, क्योंकि स्क्रिप्ट बनाए जाने के दौरान DOM में बदलाव या उसे ऐक्सेस कर सकता है.
<!-- This is a parser-blocking script: -->
<script src="/script.js"></script>
बाहरी JavaScript फ़ाइलों (async
या defer
के बिना) का इस्तेमाल करने पर, पार्सर को फ़ाइल के खोजे जाने से तब तक ब्लॉक कर दिया जाता है, जब तक कि उसे डाउनलोड, पार्स, और एक्ज़ीक्यूट नहीं कर दिया जाता. इनलाइन JavaScript का इस्तेमाल करते समय, पार्सर तब तक ब्लॉक रहता है, जब तक इनलाइन स्क्रिप्ट को पार्स और एक्ज़ीक्यूट नहीं किया जाता.
प्रीलोड स्कैनर
प्रीलोड स्कैनर एक ब्राउज़र ऑप्टिमाइज़ेशन है, जो सेकंडरी एचटीएमएल पार्सर के तौर पर होता है. यह रॉ एचटीएमएल रिस्पॉन्स को स्कैन करता है, ताकि मुख्य एचटीएमएल पार्सर के खोज करने से पहले ही, उसे खोज के और अनुमान के आधार पर फ़ेच किया जा सके. उदाहरण के लिए,
प्रीलोड स्कैनर, ब्राउज़र को <img>
एलिमेंट में बताए गए संसाधन डाउनलोड करने की अनुमति देगा, भले ही सीएसएस और JavaScript जैसे रिसॉर्स को फ़ेच और प्रोसेस करते समय, एचटीएमएल पार्सर ब्लॉक हो.
प्रीलोड स्कैनर का फ़ायदा लेने के लिए, ज़रूरी संसाधनों को सर्वर से भेजे गए एचटीएमएल मार्कअप में शामिल किया जाना चाहिए. रिसॉर्स लोड होने के इन पैटर्न को प्रीलोड स्कैनर नहीं खोज सकता:
background-image
प्रॉपर्टी का इस्तेमाल करके, सीएसएस ने इमेज लोड की हैं. ये इमेज रेफ़रंस, सीएसएस में हैं और प्रीलोड स्कैनर इन्हें नहीं खोज सकते.<script>
एलिमेंट मार्कअप के रूप में, डाइनैमिक तौर पर लोड की गई स्क्रिप्ट, जिन्हें JavaScript का इस्तेमाल करके डीओएम में इंजेक्ट किया जाता है. इसके अलावा, डाइनैमिक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}
अपने बुनियादी तौर पर कहें, तो सीएसएस छोटा करने की सुविधा एक असरदार ऑप्टिमाइज़ेशन है, जिससे आपकी वेबसाइट के एफ़सीपी और कुछ मामलों में एलसीपी भी बेहतर हो सकता है. बंडलर जैसे टूल, प्रोडक्शन के दौरान आपके लिए यह ऑप्टिमाइज़ेशन अपने-आप कर सकते हैं.
इस्तेमाल नहीं किए गए सीएसएस को हटाएं
किसी भी कॉन्टेंट को रेंडर करने से पहले, ब्राउज़र को सभी स्टाइल शीट डाउनलोड और पार्स करनी होंगी. पार्स करने में लगने वाले समय में वे स्टाइल भी शामिल हैं जो मौजूदा पेज पर इस्तेमाल नहीं की गई हैं. अगर किसी ऐसे बंडलर का इस्तेमाल किया जा रहा है जो सभी सीएसएस रिसॉर्स को एक ही फ़ाइल में जोड़ता है, तो इस बात की संभावना ज़्यादा है कि आपके उपयोगकर्ता मौजूदा पेज को रेंडर करने के लिए, ज़्यादा सीएसएस डाउनलोड कर रहे हैं.
मौजूदा पेज के लिए इस्तेमाल नहीं किए गए सीएसएस को खोजने के लिए, 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">
एलिमेंट का इस्तेमाल करके @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 से रेंडर किए गए मार्कअप, प्रीलोड स्कैनर को पूरी तरह से हटा देते हैं, क्योंकि क्लाइंट के रेंडर किए गए मार्कअप में मौजूद संसाधन खोजे नहीं जा सकते. इससे, एलसीपी इमेज जैसे अहम रिसॉर्स के डाउनलोड में देरी हो सकती है. ब्राउज़र, स्क्रिप्ट लागू होने और एलिमेंट को डीओएम में जोड़ने के बाद ही, एलसीपी इमेज डाउनलोड करना शुरू करता है. इस वजह से, स्क्रिप्ट को खोजने, डाउनलोड करने, और पार्स करने के बाद ही उसे चलाया जा सकता है. इसे गंभीर अनुरोध चेन के तौर पर जाना जाता है और इससे बचना चाहिए.
इसके अलावा, नेविगेशन अनुरोध के जवाब में सर्वर से डाउनलोड किए गए मार्कअप के मुकाबले, JavaScript का इस्तेमाल करके मार्कअप को रेंडर करने से लंबे टास्क जनरेट होने की संभावना ज़्यादा होती है. एचटीएमएल को क्लाइंट-साइड रेंडरिंग की प्रोसेस में बहुत ज़्यादा इस्तेमाल करने से, इंटरैक्शन के इंतज़ार के समय पर बुरा असर पड़ सकता है. ऐसा खास तौर पर उन मामलों में होता है जहां पेज का DOM बहुत बड़ा होता है. इससे, JavaScript से उस DOM में बदलाव करने पर, रेंडर करने का अहम काम ट्रिगर हो जाता है.
काट-छांट
सीएसएस की तरह ही, JavaScript को कम से कम करने से स्क्रिप्ट रिसॉर्स का फ़ाइल साइज़ कम हो जाता है. इससे डाउनलोड तेज़ी से हो सकता है और ब्राउज़र, JavaScript को ज़्यादा तेज़ी से पार्स और कंपाइल कर सकता है.
इसके अलावा, JavaScript का छोटा करने की सुविधा, सीएसएस जैसी दूसरी एसेट को छोटा करने से एक कदम आगे बढ़ जाती है. जब JavaScript को छोटा किया जाता है, तो उससे सिर्फ़ स्पेस, टैब, और टिप्पणियों जैसी चीज़ें नहीं हटतीं, बल्कि सोर्स JavaScript में मौजूद सिंबल को भी छोटा कर दिया जाता है. इस प्रोसेस को कभी-कभी uग्लिफ़िकेशन कहा जाता है. अंतर देखने के लिए, नीचे दिए गए 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 की
उपलब्ध सुविधाओं पर असर नहीं पड़ता.
अगर अपनी वेबसाइट के सोर्स कोड को प्रोसेस करने के लिए बंडलर का इस्तेमाल किया जा रहा है, तो प्रोडक्शन बिल्ड के लिए, अक्सर अपने-आप सुधार किया जाता है. उदाहरण के लिए, Uglifier—जैसे कि Terser—को भी अच्छी तरह से कॉन्फ़िगर किया जा सकता है. इससे आपको ज़्यादा से ज़्यादा बचत करने के लिए, अपग्रेड करने की एल्गोरिदम की एग्रेसिविटी में बदलाव करने में मदद मिलती है. हालांकि, आउटपुट साइज़ और क्षमताओं को बनाए रखने के बीच सही संतुलन बनाने के लिए, आम तौर पर किसी भी बदलाव करने वाले टूल की डिफ़ॉल्ट सेटिंग काफ़ी होती है.
JavaScript डेमो
देखें कि आपको कितना ज्ञान है
ब्राउज़र में एक से ज़्यादा सीएसएस फ़ाइलें लोड करने का सबसे अच्छा तरीका क्या है?
@import
का एलान.<link>
एलिमेंट.ब्राउज़र प्रीलोड स्कैनर क्या करता है?
<link rel="preload">
एलिमेंट का पता लगाता है.
JavaScript के रिसॉर्स डाउनलोड करते समय, ब्राउज़र डिफ़ॉल्ट रूप से एचटीएमएल को पार्स करने से कुछ समय के लिए क्यों रोक देता है?
अगला कॉन्टेंट: रिसॉर्स से जुड़े संकेतों में, ब्राउज़र की मदद करना
अब आपको यह पता है कि <head>
एलिमेंट में लोड किए गए रिसॉर्स, पेज के शुरुआती लोड और अलग-अलग मेट्रिक पर किस तरह असर डालते हैं. इसलिए, अब आगे बढ़ने का समय आ गया है. अगले मॉड्यूल में, संसाधन से जुड़े संकेतों के बारे में बताया गया है. साथ ही, यह भी बताया गया है कि कैसे वे संसाधनों को लोड करने और क्रॉस-ऑरिजिन सर्वर के कनेक्शन को, ब्राउज़र के बिना जल्द से जल्द लोड करने के लिए, ब्राउज़र को काम के संकेत दे सकते हैं.