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

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

इनलाइन इमेज

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

ब्राउज़र-लेवल की लेज़ी लोडिंग का इस्तेमाल किया जा रहा है

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

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

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

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

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

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

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

अलग-अलग इवेंट हैंडलर पर निर्भर कोड के बजाय, 'इंटरसेक्शन ऑब्ज़र्वर' को इस्तेमाल करना और पढ़ना ज़्यादा आसान होता है. ऐसा इसलिए है, क्योंकि आपको एलिमेंट देखने के लिए मुश्किल एलिमेंट 'किसको दिखे' कोड लिखने के बजाय, सिर्फ़ एलिमेंट देखने के लिए एक ऑब्ज़र्वर रजिस्टर करना होता है. अब यह तय करना है कि एलिमेंट के दिखने पर क्या करना है. आपके लेज़ी लोड किए गए <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 का इस्तेमाल करके, सीएसएस में इमेज लोड होने से रोकने के लिए किया जा सकता है. इसके लिए, 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 का इस्तेमाल करके यह देखें कि एलिमेंट व्यूपोर्ट में (इंटरसेक्शन ऑब्ज़र्वर के साथ!) है या नहीं. साथ ही, उस समय div.lazy-background एलिमेंट में visible क्लास जोड़ें, जिससे इमेज लोड होगी:

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 लेज़ी लोड होने वाली इमेज, बैकग्राउंड इमेज, वीडियो, iframes, और स्क्रिप्ट के लिए एक लाइटवेट विकल्प है. यह इंटरसेक्शन ऑब्ज़र्वर का इस्तेमाल करता है, रिस्पॉन्सिव इमेज के साथ काम करता है, और ब्राउज़र-लेवल पर लेज़ी लोडिंग को चालू करता है.
  • lozad.js एक और हल्का विकल्प है, जो सिर्फ़ 'इंटरसेक्शन ऑब्ज़र्वर' का इस्तेमाल करता है. इसलिए, यह बेहतर परफ़ॉर्म करता है. लेकिन पुराने ब्राउज़र पर इसे इस्तेमाल करने से पहले इसे पॉलीफ़िल करना होगा.
  • अगर आपको प्रतिक्रिया के हिसाब से लेज़ी लोडिंग लाइब्रेरी की ज़रूरत है, तो react-lazyload करें. यह 'इंटरसेक्शन ऑब्ज़र्वर' का इस्तेमाल नहीं करता है, लेकिन यह उन लोगों के लिए लेज़ी लोडिंग का एक जाना-पहचाना तरीका उपलब्ध करता है जो रिऐक्ट वाले ऐप्लिकेशन डेवलप करने के आदी हैं.