लेज़ी लोडिंग के सबसे सही तरीके

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

फ़ोल्ड का ध्यान रखें

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

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

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

इसके अलावा, हो सकता है कि आप फ़ोल्ड लाइन को लेकर इतना सख्त न हों, कि लेज़ी लोडिंग को ट्रिगर करने के लिए तय की गई सीमा. बफ़र ज़ोन को वेबसाइट में फ़ोल्ड के नीचे कुछ दूरी पर सेट करना बेहतर होता है. इससे, इमेज को व्यूपोर्ट में स्क्रोल करने से पहले ही, इमेज लोड होने लगती हैं. उदाहरण के लिए, जब आप कोई नया IntersectionObserver इंस्टेंस बनाते हैं, तो Intersection Observer API की मदद से विकल्प ऑब्जेक्ट में rootMargin प्रॉपर्टी तय की जा सकती है. इससे एलिमेंट को असरदार तरीके से एक बफ़र मिलता है, जो व्यूपोर्ट में एलिमेंट के आने से पहले ही लेज़ी लोडिंग को ट्रिगर करता है:

let lazyImageObserver = new IntersectionObserver(function(entries, observer) {
  // lazy-loading image code goes here
}, {
  rootMargin: "0px 0px 256px 0px"
});

अगर rootMargin की वैल्यू, सीएसएस margin प्रॉपर्टी के लिए तय की गई वैल्यू से मिलती-जुलती है, तो ऐसा इसलिए है! इस मामले में, निगरानी में रखे गए एलिमेंट का निचला मार्जिन (डिफ़ॉल्ट रूप से ब्राउज़र का व्यूपोर्ट, होता है. हालांकि, इसे root प्रॉपर्टी का इस्तेमाल करके किसी खास एलिमेंट में बदला जा सकता है) को 256 पिक्सल तक बढ़ा दिया जाता है. इसका मतलब है कि जब कोई इमेज एलिमेंट, व्यूपोर्ट के 256 पिक्सल के अंदर होगा, तो कॉलबैक फ़ंक्शन काम करेगा. साथ ही, उपयोगकर्ता के देखने से पहले ही इमेज लोड होने लगेगी.

जो ब्राउज़र 'इंटरसेक्शन निरीक्षण' के साथ काम नहीं करते हैं, उनमें यही इफ़ेक्ट पाने के लिए, स्क्रोल इवेंट हैंडलिंग कोड का इस्तेमाल करें. साथ ही, बफ़र को शामिल करने के लिए अपने getBoundingClientRect चेक में बदलाव करें.

लेआउट शिफ़्टिंग और प्लेसहोल्डर

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

<img> टैग के लिए, src को शुरुआत में प्लेसहोल्डर पर ले जाना चाहिए. ऐसा तब तक होना चाहिए, जब तक उस एट्रिब्यूट को फ़ाइनल इमेज के यूआरएल के साथ अपडेट न कर दिया जाए. प्लेसहोल्डर इमेज पर ले जाने के लिए, <video> एलिमेंट में poster एट्रिब्यूट का इस्तेमाल करें. इसके अलावा, <img> और <video>, दोनों टैग में width और height एट्रिब्यूट का इस्तेमाल करें. इससे यह पक्का होता है कि प्लेसहोल्डर से फ़ाइनल इमेज पर जाने से, मीडिया लोड होने पर एलिमेंट का रेंडर किया गया साइज़ नहीं बदलेगा.

इमेज डिकोड करने में देरी

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

var newImage = new Image();
newImage.src = "my-awesome-image.jpg";

if ("decode" in newImage) {
  // Fancy decoding logic
  newImage.decode().then(function() {
    imageContainer.appendChild(newImage);
  });
} else {
  // Regular image load
  imageContainer.appendChild(newImage);
}

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

चीज़ें लोड न होने पर

कभी-कभी मीडिया संसाधन किसी एक वजह से लोड नहीं हो पाते हैं और कभी-कभी गड़बड़ियां हो जाती हैं. ऐसा कब हो सकता है? यह निर्भर करता है, लेकिन यहां आपके लिए एक काल्पनिक स्थिति है: आपने कुछ समय (जैसे, पांच मिनट) के लिए एचटीएमएल को कैश मेमोरी में सेव करने की नीति सेट की है और उपयोगकर्ता साइट पर आता है या वह उपयोगकर्ता लंबे समय से पुराना टैब खुला रखता है (जैसे, कई घंटे) और आपका कॉन्टेंट पढ़ने के लिए वापस आता है. इस प्रोसेस के कभी-कभी फिर से डिप्लॉयमेंट किया जाता है. डिप्लॉयमेंट के दौरान, हैश पर आधारित वर्शन की वजह से इमेज रिसॉर्स का नाम बदल जाता है या एक साथ हटा दिया जाता है. जब तक उपयोगकर्ता इमेज को लेज़ी-लोड करता है, तब तक संसाधन उपलब्ध नहीं होता और इस वजह से काम नहीं करता.

हालांकि, ऐसा कम ही होता है, लेकिन अगर लेज़ी लोडिंग फ़ेल हो जाए, तो हो सकता है कि आपके पास बैकअप प्लान हो. इमेज के लिए, समाधान कुछ ऐसा दिख सकता है:

var newImage = new Image();
newImage.src = "my-awesome-image.jpg";

newImage.onerror = function(){
  // Decide what to do on error
};
newImage.onload = function(){
  // Load the image
};

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

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

JavaScript की उपलब्धता

यह नहीं मानना चाहिए कि JavaScript हमेशा उपलब्ध है. अगर इमेज को लेज़ी-लोड किया जा रहा है, तो <noscript> मार्कअप दें. JavaScript उपलब्ध न होने पर इमेज दिखेंगी. फ़ॉलबैक के सबसे आसान उदाहरण में, इमेज दिखाने के लिए <noscript> एलिमेंट का इस्तेमाल करना शामिल है. ऐसा JavaScript के बंद होने पर किया जाता है:

मैं एक इमेज हूं!

अगर JavaScript बंद है, तो उपयोगकर्ताओं को प्लेसहोल्डर इमेज और <noscript> एलिमेंट वाली इमेज, दोनों दिखेंगी. इससे बचने के लिए, <html> टैग पर no-js की एक क्लास इस तरह से रखें:

<html class="no-js">

इसके बाद, <link> टैग की मदद से किसी भी स्टाइल शीट का अनुरोध करने से पहले, इनलाइन स्क्रिप्ट की एक लाइन <head> में रखें. इससे, JavaScript के चालू होने पर, <html> एलिमेंट से no-js क्लास हट जाती है:

<script>document.documentElement.classList.remove("no-js");</script>

आखिर में, JavaScript के उपलब्ध न होने पर, लेज़ी क्लास वाले एलिमेंट छिपाने के लिए कुछ सीएसएस का इस्तेमाल करें:

.no-js .lazy {
  display: none;
}

इससे प्लेसहोल्डर इमेज लोड होने से नहीं रुकतीं, लेकिन नतीजा बेहतर होता है. जिन लोगों ने JavaScript की सुविधा बंद की है उन्हें प्लेसहोल्डर इमेज के अलावा, कुछ और चीज़ें भी मिलती हैं. यह प्लेसहोल्डर इमेज से बेहतर होता है और इसमें कोई अहम इमेज कॉन्टेंट नहीं होता.