बड़े, जटिल लेआउट और लेआउट थ्रेशिंग से बचें

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

लेआउट वह जगह है जहां ब्राउज़र एलिमेंट की ज्यामितीय जानकारी दिखाता है: पेज पर उनका साइज़ और जगह की जानकारी. हर एलिमेंट में, इस्तेमाल किए गए सीएसएस, एलिमेंट के कॉन्टेंट या पैरंट एलिमेंट के हिसाब से, उसके साइज़ की जानकारी साफ़ तौर पर या किसी दूसरे एलिमेंट में दी गई होगी. इस प्रोसेस को Chrome (और डिराइव्ड ब्राउज़र जैसे कि Edge) और Safari में लेआउट कहा जाता है. Firefox में इसे Reflow कहा जाता है, लेकिन इसकी प्रक्रिया असल में एक जैसी है.

स्टाइल कैलकुलेशन की तरह ही, लेआउट की लागत से जुड़े सवाल भी हैं:

  1. ऐसे एलिमेंट की संख्या जिनके लिए लेआउट की ज़रूरत होती है, जो पेज के DOM साइज़ का एक प्रॉडक्ट है.
  2. उन लेआउट की जटिलता.

खास जानकारी

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

इंटरैक्शन इंतज़ार के समय पर लेआउट का असर

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

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

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

जहां भी हो सके, लेआउट का इस्तेमाल न करें

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

.box {
  width: 20px;
  height: 20px;
}

/**
  * Changing width and height
  * triggers layout.
  */

.box--expanded {
  width: 200px;
  height: 350px;
}

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

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

DevTools देर से लेआउट में दिख रहा है.

ऊपर दिए गए उदाहरण में ट्रेस की जांच करने पर, हम देखते हैं कि हर फ़्रेम के लिए लेआउट में 28 मिलीसेकंड से ज़्यादा खर्च होता है, जो कि जब हमारे पास किसी ऐनिमेशन में स्क्रीन पर फ़्रेम लेने के लिए 16 मिलीसेकंड होते हैं, तो वह बहुत ज़्यादा होता है. यह भी देखा जा सकता है कि DevTools आपको ट्री का साइज़ (इस मामले में 1,618 एलिमेंट) और लेआउट के लिए कितने नोड चाहिए (इस मामले में 5) बताएगा.

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

फ़ोर्स्ड सिंक्रोनस लेआउट का इस्तेमाल न करें

किसी फ़्रेम को स्क्रीन पर भेजने का यह ऑर्डर होता है:

लेआउट के तौर पर फ़्लेक्सबॉक्स का इस्तेमाल किया जा रहा है.

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

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

// Schedule our function to run at the start of the frame:
requestAnimationFrame(logBoxHeight);

function logBoxHeight () {
  // Gets the height of the box in pixels and logs it out:
  console.log(box.offsetHeight);
}

अगर आपने बॉक्स की ऊंचाई के बारे में पूछने से पहले ही उसकी स्टाइल बदल दी है, तो चीज़ों में समस्या पैदा हो जाती है:

function logBoxHeight () {
  box.classList.add('super-big');

  // Gets the height of the box in pixels and logs it out:
  console.log(box.offsetHeight);
}

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

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

सही तरीके से करने पर ऊपर दिया गया फ़ंक्शन यह होगा:

function logBoxHeight () {
  // Gets the height of the box in pixels and logs it out:
  console.log(box.offsetHeight);

  box.classList.add('super-big');
}

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

लेआउट थ्रैशिंग से बचें

फ़ोर्स किए गए सिंक्रोनस लेआउट को और भी खराब बनाने का एक तरीका है: एक के बाद एक कई लगातार करें. इस कोड को देखें:

function resizeAllParagraphsToMatchBlockWidth () {
  // Puts the browser into a read-write-read-write cycle.
  for (let i = 0; i < paragraphs.length; i++) {
    paragraphs[i].style.width = `${box.offsetWidth}px`;
  }
}

यह कोड, पैराग्राफ़ के ग्रुप के ऊपर लूप में चलता है और हर पैराग्राफ़ की चौड़ाई को "box" नाम के एलिमेंट की चौड़ाई से मेल खाने के लिए सेट करता है. इससे कोई नुकसान नहीं पहुंचता है, लेकिन समस्या यह है कि लूप के हर इटरेशन से एक स्टाइल वैल्यू (box.offsetWidth) को पढ़ा जाता है. साथ ही, फिर वह तुरंत पैराग्राफ़ (paragraphs[i].style.width) की चौड़ाई को अपडेट करने के लिए इसका इस्तेमाल करता है. लूप की अगली इटरेशन पर, ब्राउज़र को यह ध्यान रखना होगा कि offsetWidth के पिछली बार अनुरोध करने के बाद, स्टाइल बदल गए हैं (पिछले इटरेशन में), और इसलिए उसे स्टाइल में बदलाव और लेआउट चलाना होगा. ऐसा हर एक बार पर होगा!.

इस सैंपल को ठीक करने के लिए, एक बार फिर से पढ़ें और फिर वैल्यू लिखें

// Read.
const width = box.offsetWidth;

function resizeAllParagraphsToMatchBlockWidth () {
  for (let i = 0; i < paragraphs.length; i++) {
    // Now write.
    paragraphs[i].style.width = `${width}px`;
  }
}

अगर आपको सुरक्षा की गारंटी देनी है, तो FastDOM का इस्तेमाल करें. यह आपके लिए, पढ़े और लिखे गए कॉन्टेंट को अपने-आप बैच में बनाता है. साथ ही, इससे आपको फ़ोर्स किए गए सिंक्रोनस लेआउट या लेआउट को गलती से थ्रैशिंग होने से बचाने में भी मदद मिलती है.

Hal Gatewood की ओर से Unस्प्लैश की हीरो इमेज.