लेज़ी लोडिंग इमेज

एचटीएमएल में <img> एलिमेंट या सीएसएस बैकग्राउंड इमेज के तौर पर इनलाइन होने की वजह से, इमेज किसी वेबपेज पर दिख सकती हैं. इस पोस्ट में आपको दोनों तरह की इमेज को लेज़ी-लोड करने का तरीका पता चलेगा.

इनलाइन इमेज

<img> एलिमेंट में इस्तेमाल की गई इमेज, लेज़ी लोडिंग के सबसे आम कैंडिडेट होते हैं. इनलाइन इमेज के साथ हमारे पास लेज़ी लोडिंग के तीन विकल्प हैं, जिनका इस्तेमाल सभी ब्राउज़र पर सबसे अच्छी तरह से काम करने के लिए किया जा सकता है:

ब्राउज़र लेवल पर लेज़ी लोडिंग की सुविधा का इस्तेमाल करना

Chrome और Firefox, दोनों ही loading एट्रिब्यूट के साथ लेज़ी लोडिंग के साथ काम करते हैं. इस एट्रिब्यूट को <img> एलिमेंट में और <iframe> एलिमेंट में भी जोड़ा जा सकता है. lazy की वैल्यू, ब्राउज़र को इमेज के व्यूपोर्ट में तुरंत लोड करने के लिए कहती है. साथ ही, जब उपयोगकर्ता इमेज के आस-पास स्क्रोल करता है, तो उसे दूसरी इमेज को फ़ेच करने के लिए भी कहा जाता है.

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

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

ज़्यादा जानने के लिए, वेब के लिए ब्राउज़र-लेवल पर लेज़ी लोडिंग लेख देखें.

इंटरसेक्शन ऑब्ज़र्वर का इस्तेमाल करना

<img> एलिमेंट की लेज़ी लोडिंग की पॉलीफ़िल के लिए, हम JavaScript का इस्तेमाल करते हैं. इससे यह पता चलता है कि वे व्यूपोर्ट में मौजूद हैं या नहीं. अगर ऐसा है, तो उनके src (और कभी-कभी srcset) एट्रिब्यूट में, मनचाही इमेज के यूआरएल शामिल होते हैं.

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

अलग-अलग इवेंट हैंडलर पर निर्भर कोड के मुकाबले, इंटरसेक्शन ऑब्ज़र्वर को इस्तेमाल करना और पढ़ना आसान है, क्योंकि आपको एलिमेंट को देखने के लिए सिर्फ़ ऑब्ज़र्वर को रजिस्टर करना होगा, न कि एलिमेंट को देखने के लिए मुश्किल एलिमेंट का पता लगाने वाला कोड लिखने के बजाय. बस, बस यह तय करना बाकी है कि एलिमेंट के दिखने पर क्या करना है. चलिए, आपके लेज़ी लोड किए गए <img> एलिमेंट के लिए इस बेसिक मार्कअप पैटर्न को मान लेते हैं:

<img class="lazy" src="placeholder-image.jpg" data-src="image-to-lazy-load-1x.jpg" data-srcset="image-to-lazy-load-2x.jpg 2x, image-to-lazy-load-1x.jpg 1x" alt="I'm an image!">

इस मार्कअप के तीन ज़रूरी हिस्से हैं जिन पर आपको ध्यान देना चाहिए:

  1. class एट्रिब्यूट. इसी एट्रिब्यूट का इस्तेमाल करके, JavaScript में एलिमेंट को चुना जाएगा.
  2. src एट्रिब्यूट, जो एक प्लेसहोल्डर इमेज का रेफ़रंस देता है, जो पहली बार पेज लोड होने पर दिखेगी.
  3. data-src और data-srcset एट्रिब्यूट, प्लेसहोल्डर एट्रिब्यूट होते हैं. इनमें उस इमेज का यूआरएल होता है जिसे एलिमेंट के व्यूपोर्ट में होने पर लोड किया जाता है.

अब देखते हैं कि इस मार्कअप पैटर्न का इस्तेमाल करके, इमेज को लेज़ी-लोड करने के लिए, JavaScript में इंटरसेक्शन ऑब्ज़र्वर का इस्तेमाल कैसे करें:

document.addEventListener("DOMContentLoaded", function() {
  var lazyImages = [].slice.call(document.querySelectorAll("img.lazy"));

  if ("IntersectionObserver" in window) {
    let lazyImageObserver = new IntersectionObserver(function(entries, observer) {
      entries.forEach(function(entry) {
        if (entry.isIntersecting) {
          let lazyImage = entry.target;
          lazyImage.src = lazyImage.dataset.src;
          lazyImage.srcset = lazyImage.dataset.srcset;
          lazyImage.classList.remove("lazy");
          lazyImageObserver.unobserve(lazyImage);
        }
      });
    });

    lazyImages.forEach(function(lazyImage) {
      lazyImageObserver.observe(lazyImage);
    });
  } else {
    // Possibly fall back to event handlers here
  }
});

दस्तावेज़ के DOMContentLoaded इवेंट पर, यह स्क्रिप्ट lazy क्लास वाले सभी <img> एलिमेंट के लिए डीओएम से क्वेरी करती है. अगर इंटरसेक्शन ऑब्ज़र्वर उपलब्ध है, तो एक नया ऑब्ज़र्वर बनाएं, जो img.lazy एलिमेंट के व्यूपोर्ट में शामिल होने पर कॉलबैक चलाता हो.

इंटरसेक्शन ऑब्ज़र्वर सभी मॉडर्न ब्राउज़र में उपलब्ध है. इसलिए, loading="lazy" के लिए इसे पॉलीफ़िल के तौर पर इस्तेमाल करने से, यह पक्का होगा कि वेबसाइट पर आने वाले ज़्यादातर लोगों के लिए लेज़ी लोडिंग की सुविधा उपलब्ध है.

सीएसएस में मौजूद इमेज

हालांकि, <img> टैग, वेब पेजों पर इमेज का इस्तेमाल करने का सबसे आम तरीका है, लेकिन सीएसएस background-image प्रॉपर्टी (और दूसरी प्रॉपर्टी) के ज़रिए भी इमेज को शुरू किया जा सकता है. ब्राउज़र-लेवल की लेज़ी लोडिंग, सीएसएस के बैकग्राउंड की इमेज पर लागू नहीं होती. इसलिए, अगर आपके पास बैकग्राउंड की इमेज को लेज़ी-लोड करना है, तो आपको दूसरे तरीके अपनाने होंगे.

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

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

<div class="lazy-background">
  <h1>Here's a hero heading to get your attention!</h1>
  <p>Here's hero copy to convince you to buy a thing!</p>
  <a href="/buy-a-thing">Buy a thing!</a>
</div>

आम तौर पर, div.lazy-background एलिमेंट में हीरो बैकग्राउंड इमेज मौजूद होती है, जिसे कुछ सीएसएस इस्तेमाल करते हैं. हालांकि, लेज़ी लोडिंग के इस उदाहरण में, व्यूपोर्ट में होने पर एलिमेंट में जोड़ी गई visible क्लास की मदद से, div.lazy-background एलिमेंट की background-image प्रॉपर्टी को अलग किया जा सकता है:

.lazy-background {
  background-image: url("hero-placeholder.jpg"); /* Placeholder image */
}

.lazy-background.visible {
  background-image: url("hero.jpg"); /* The final image */
}

यहां से, यह देखने के लिए JavaScript का इस्तेमाल करें कि एलिमेंट, व्यूपोर्ट (इंटरसेक्शन ऑब्ज़र्वर के साथ!) में है या नहीं. साथ ही, उस समय visible क्लास को div.lazy-background एलिमेंट में जोड़ें, जिससे इमेज लोड हो जाती है:

document.addEventListener("DOMContentLoaded", function() {
  var lazyBackgrounds = [].slice.call(document.querySelectorAll(".lazy-background"));

  if ("IntersectionObserver" in window) {
    let lazyBackgroundObserver = new IntersectionObserver(function(entries, observer) {
      entries.forEach(function(entry) {
        if (entry.isIntersecting) {
          entry.target.classList.add("visible");
          lazyBackgroundObserver.unobserve(entry.target);
        }
      });
    });

    lazyBackgrounds.forEach(function(lazyBackground) {
      lazyBackgroundObserver.observe(lazyBackground);
    });
  }
});

सबसे बड़े एलिमेंट को रेंडर करने में लगने वाले समय (एलसीपी) पर असर

लेज़ी लोडिंग, एक बेहतरीन ऑप्टिमाइज़ेशन है. इससे शुरू होने के दौरान, डेटा खर्च और नेटवर्क की समस्या, दोनों को कम किया जा सकता है. इससे इमेज लोड होने में देरी होती है, ताकि वे ज़रूरत के समय ही लोड हो पाएं. इससे इमेज के शुरू होने में लगने वाला समय बढ़ सकता है. साथ ही, इमेज डीकोड करने में लगने वाले समय को कम करके, मुख्य थ्रेड पर प्रोसेसिंग कम हो सकती है.

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

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

यहां तक कि किसी इन-व्यूपोर्ट इमेज को लेज़ी लोड करने के लिए, ब्राउज़र-लेवल पर लेज़ी लोडिंग का इस्तेमाल करने पर भी बुरा असर पड़ सकता है. जब loading="lazy" को किसी इन-व्यूपोर्ट इमेज पर लागू किया जाता है, तो वह इमेज तब तक देरी से दिखेगी, जब तक ब्राउज़र को यह पता नहीं चल जाता कि वह व्यूपोर्ट में है. इससे किसी पेज के एलसीपी पर असर पड़ सकता है.

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

लेज़ी लोडिंग लाइब्रेरी

जब भी हो सके, आपको ब्राउज़र-लेवल पर लेज़ी लोडिंग का इस्तेमाल करना चाहिए. हालांकि, अगर आपको ऐसी स्थिति में जाना चाहिए जहां यह विकल्प उपलब्ध न हो, जैसे कि पुराने ब्राउज़र का इस्तेमाल करने वाले उपयोगकर्ताओं का एक बड़ा ग्रुप, तो इमेज को लेज़ी-लोड करने के लिए, इन लाइब्रेरी का इस्तेमाल किया जा सकता है:

  • lazysizes, लेज़ी लोडिंग वाली एक पूरी सुविधा वाली लाइब्रेरी है. यह इमेज और iframe को लेज़ी-लोड करती है. इसका इस्तेमाल, यहां दिए गए कोड उदाहरणों से काफ़ी मिलता-जुलता है. यह <img> एलिमेंट पर अपने-आप lazyload क्लास से जुड़ जाता है. इसके लिए, आपको data-src और/या data-srcset एट्रिब्यूट में इमेज के यूआरएल डालने होंगे. इसका कॉन्टेंट, src और/या srcset एट्रिब्यूट में बदल दिया जाता है. यह इंटरसेक्शन ऑब्ज़र्वर का इस्तेमाल करता है (जिसे पॉलीफ़िल किया जा सकता है). साथ ही, लेज़ी-लोड वीडियो जैसे काम करने के लिए, इसे कई प्लगिन के साथ बढ़ाया जा सकता है. लेज़ीसाइज़ के इस्तेमाल के बारे में ज़्यादा जानें.
  • vanilla-lazyload, लेज़ी लोडिंग इमेज, बैकग्राउंड इमेज, वीडियो, iframe, और स्क्रिप्ट के लिए एक लाइटवेट विकल्प है. यह इंटरसेक्शन ऑब्ज़र्वर का इस्तेमाल करता है, रिस्पॉन्सिव इमेज के साथ काम करता है, और ब्राउज़र-लेवल पर लेज़ी लोडिंग को चालू करता है.
  • lozad.js एक और लाइटवेट विकल्प है, जो सिर्फ़ इंटरसेक्शन ऑब्ज़र्वर का इस्तेमाल करता है. इस तरह, यह बेहतर परफ़ॉर्म करता है, लेकिन पुराने ब्राउज़र पर इसका इस्तेमाल करने से पहले इसे पॉलीफ़िल करना होगा.
  • अगर आपको रिऐक्ट के हिसाब से लेज़ी लोडिंग वाली लाइब्रेरी की ज़रूरत है, तो रिऐक्ट-लेज़ीलोड का इस्तेमाल करें. यह इंटरसेक्शन ऑब्ज़र्वर का इस्तेमाल नहीं करता, लेकिन यह उन लोगों के लिए लेज़ी लोडिंग इमेज का जाना-पहचाना तरीका उपलब्ध करता है जो React की मदद से ऐप्लिकेशन डेवलप करने में माहिर हैं.