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

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

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

स्टाइल की गणना की तरह ही, लेआउट की लागत से जुड़ी तुरंत समस्याएं ये हैं:

  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 एलिमेंट) और कितने नोड को लेआउट की ज़रूरत थी (इस मामले में पांच) बताएगा.

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

एक साथ सिंक होने वाले लेआउट से बचना

फ़्रेम को स्क्रीन पर शिप करने का क्रम यह है:

लेआउट के तौर पर फ़्लेक्सबॉक्स का इस्तेमाल करना.

सबसे पहले 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 का इस्तेमाल करें. यह आपके लिए, डेटा को पढ़ने और लिखने की प्रोसेस को अपने-आप बैच में करता है. इससे, आपको अनजाने में फ़ोर्स्ड सिंक्रोनस लेआउट या लेआउट थ्रैशिंग को ट्रिगर करने से रोका जा सकता है.