तीसरे पक्ष का JavaScript ऑप्टिमाइज़ करना

तीसरे पक्ष की स्क्रिप्ट की परफ़ॉर्मेंस पर असर पड़ता है. इसलिए, यह ज़रूरी है कि आप नियमित रूप से उनका ऑडिट करें और लोड करने के लिए बेहतर तकनीकों का इस्तेमाल करें. इस कोडलैब में, तीसरे पक्ष के संसाधनों की लोडिंग को ऑप्टिमाइज़ करने का तरीका बताया गया है. इसमें इन तकनीकों के बारे में बताया गया है:

  • स्क्रिप्ट लोड होने में देरी हो रही है

  • गैर-ज़रूरी संसाधन लेज़ी लोडिंग

  • ज़रूरी ऑरिजिन से पहले से कनेक्ट करना

शामिल किए गए नमूना ऐप्लिकेशन में एक सरल वेब पेज होता है, जिसमें तीसरे पक्ष के स्रोतों से आने वाली तीन सुविधाएं होती हैं:

  • एक वीडियो एम्बेड

  • लाइन ग्राफ़ को रेंडर करने के लिए, डेटा-विज़ुअलाइज़ेशन लाइब्रेरी

  • सोशल मीडिया पर शेयर करने वाला विजेट

उस पेज का स्क्रीनशॉट जिसमें तीसरे पक्ष के संसाधनों को हाइलाइट किया गया है.
सैंपल ऐप्लिकेशन में तीसरे पक्ष के संसाधन.

सबसे पहले आपको ऐप्लिकेशन की परफ़ॉर्मेंस का आकलन करना होगा. इसके बाद, हर तकनीक का इस्तेमाल करके ऐप्लिकेशन की परफ़ॉर्मेंस के अलग-अलग पहलुओं को बेहतर बनाना होगा.

परफ़ॉर्मेंस का आकलन करना

पहले ऐप्लिकेशन को फुलस्क्रीन व्यू में खोलें:

  1. प्रोजेक्ट में बदलाव करने के लिए, बदलाव करने के लिए रीमिक्स करें पर क्लिक करें.
  2. साइट की झलक देखने के लिए, ऐप्लिकेशन देखें दबाएं. इसके बाद, फ़ुलस्क्रीन फ़ुलस्क्रीन दबाएं.

बेसलाइन परफ़ॉर्मेंस तय करने के लिए, पेज पर Lighthouse परफ़ॉर्मेंस ऑडिट करें:

  1. DevTools खोलने के लिए, `Control+Shift+J` (या Mac पर `Command+Option+J`) दबाएं.
  2. लाइटहाउस टैब पर क्लिक करें.
  3. मोबाइल पर क्लिक करें.
  4. परफ़ॉर्मेंस चेकबॉक्स चुनें. (आपके पास ऑडिट सेक्शन के बाकी चेकबॉक्स हटाने का विकल्प भी है.)
  5. सिम्युलेटेड फ़ास्ट 3G, 4x सीपीयू स्लोडाउन पर क्लिक करें.
  6. स्टोरेज खाली करें चेकबॉक्स को चुनें.
  7. ऑडिट चलाएं पर क्लिक करें.

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

Lighthouse ऑडिट का स्क्रीनशॉट, जिसमें 2.4 सेकंड एफ़सीपी और दो मौके दिखाए गए हैं: रेंडर ब्लॉक करने वाले संसाधनों को हटाएं और ज़रूरी ऑरिजिन से Preconnect करें.

तीसरे पक्ष की JavaScript को कुछ समय के लिए रोकें

रेंडर ब्लॉक करने वाले संसाधनों को हटाएं ऑडिट से पता चला है कि d3js.org से आने वाली स्क्रिप्ट को रोककर, कुछ समय बचाया जा सकता है:

हाइलाइट की गई d3.v3.min.js स्क्रिप्ट के साथ रेंडर ब्लॉक करने वाले रिसॉर्स ऑडिट को हटाने का स्क्रीनशॉट.

D3.js डेटा विज़ुअलाइज़ेशन बनाने के लिए एक JavaScript लाइब्रेरी है. सैंपल ऐप्लिकेशन में मौजूद script.js फ़ाइल, SVG लाइन चार्ट बनाने और उसे पेज में जोड़ने के लिए, D3 यूटिलिटी फ़ंक्शन का इस्तेमाल करती है. यहां कार्रवाइयों का क्रम मायने रखता है: script.js को दस्तावेज़ को पार्स करने और D3 लाइब्रेरी के लोड होने के बाद चलाना होता है. इसलिए, इसे index.html में क्लोज़िंग </body> टैग से ठीक पहले शामिल किया जाता है.

हालांकि, D3 स्क्रिप्ट पेज के <head> में शामिल है, जो बाकी दस्तावेज़ को पार्स करने से रोकती है:

index.html का स्क्रीनशॉट, जिसके हेड में हाइलाइट किया गया स्क्रिप्ट टैग है.

स्क्रिप्ट टैग में जोड़े जाने पर दो मैजिक एट्रिब्यूट, पार्सर को अनब्लॉक कर सकते हैं:

  • async यह पक्का करता है कि स्क्रिप्ट, बैकग्राउंड में डाउनलोड हों और डाउनलोड होने के बाद पहले मौके पर काम करें.

  • defer यह पक्का करता है कि स्क्रिप्ट बैकग्राउंड में डाउनलोड हों और पार्स करने के बाद पूरी तरह से लागू हो जाएं.

यह चार्ट पूरे पेज के लिए असल में ज़रूरी नहीं है और इसमें फ़ोल्ड के नीचे होने की काफ़ी संभावना है. इसलिए, defer का इस्तेमाल करके यह पक्का करें कि कोई पार्सर ब्लॉक न हो.

पहला चरण: defer एट्रिब्यूट की मदद से, स्क्रिप्ट को एसिंक्रोनस रूप से लोड करना

index.html की लाइन 17 में, <script> एलिमेंट में defer एट्रिब्यूट जोड़ें:

<script src="https://d3js.org/d3.v3.min.js" defer></script>

दूसरा चरण: पक्का करना कि कार्रवाइयां सही क्रम में हों

अब जबकि D3 को फ़िलहाल टाल दिया गया है, इसलिए D3 के तैयार होने से पहले script.js चलेगा. इससे एक गड़बड़ी हो सकती है.

defer एट्रिब्यूट वाली स्क्रिप्ट उसी क्रम में काम करती हैं जिसमें उन्हें दिखाया गया था. यह पक्का करने के लिए कि D3 तैयार होने के बाद script.js एक्ज़ीक्यूट हो, इसमें defer जोड़ें और उसे D3 <script> एलिमेंट के ठीक बाद, दस्तावेज़ के <head> में ले जाएं. अब यह पार्सर को ब्लॉक नहीं करता है और डाउनलोड जल्द शुरू हो जाता है.

<script src="https://d3js.org/d3.v3.min.js" defer></script>
<script src="./script.js" defer></script>

तीसरे पक्ष के संसाधनों को लेज़ी-लोड करें

वेबसाइट में फ़ोल्ड के नीचे मौजूद सभी संसाधन, लेज़ी लोडिंग के लिए अच्छे होते हैं.

सैंपल ऐप्लिकेशन में, iframe में एम्बेड किया गया YouTube वीडियो मौजूद है. यह देखने के लिए कि पेज कितने अनुरोध करता है और कौन-कौनसे पेज, एम्बेड किए गए YouTube iframe से आते हैं:

  1. साइट की झलक देखने के लिए, ऐप्लिकेशन देखें दबाएं. इसके बाद, फ़ुलस्क्रीन फ़ुलस्क्रीन दबाएं.
  2. DevTools खोलने के लिए, `Control+Shift+J` (या Mac पर `Command+Option+J`) दबाएं.
  3. नेटवर्क टैब पर क्लिक करें.
  4. कैश मेमोरी बंद करें चेकबॉक्स चुनें.
  5. Throttling ड्रॉपडाउन मेन्यू में फ़ास्ट 3G चुनें.
  6. पेज को फिर से लोड करें.

DevTools नेटवर्क पैनल का स्क्रीनशॉट.

नेटवर्क पैनल से पता चलता है कि पेज ने कुल 28 अनुरोध किए और करीब 1 एमबी कंप्रेस किए गए रिसॉर्स ट्रांसफ़र किए.

YouTube iframe के किए गए अनुरोधों की पहचान करने के लिए, शुरू करने वाला कॉलम में वीडियो आईडी 6lfaiXM6waw देखें. डोमेन के हिसाब से सभी अनुरोधों को एक साथ ग्रुप करने के लिए:

  • नेटवर्क पैनल में, कॉलम के शीर्षक पर राइट क्लिक करें.

  • ड्रॉपडाउन मेन्यू में, डोमेन कॉलम चुनें.

  • डोमेन के मुताबिक अनुरोधों को क्रम से लगाने के लिए, डोमेन कॉलम के टाइटल पर क्लिक करें.

नए क्रम से लगाने से पता चलता है कि Google डोमेन के लिए और भी अनुरोध हैं. YouTube iframe, स्क्रिप्ट, स्टाइलशीट, इमेज, और फ़ॉन्ट के लिए कुल 14 अनुरोध करता है. हालांकि, जब तक उपयोगकर्ता वीडियो चलाने के लिए नीचे की ओर स्क्रोल नहीं करते, तब तक उन्हें उन सभी ऐसेट की ज़रूरत नहीं होती.

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

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

पहला चरण: शुरुआत में वीडियो को लोड होने से रोकना

वीडियो iframe को लेज़ी-लोड करने के लिए, आपको पहले इसे सामान्य तरीके से लोड होने से रोकना होगा. ऐसा करने के लिए, src एट्रिब्यूट की जगह data-src एट्रिब्यूट का इस्तेमाल करें. इससे वीडियो के यूआरएल के बारे में जानकारी मिलेगी:

<iframe width="560" height="315" data-src="https://www.youtube.com/embed/lS9D6w1GzGY" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>

data-src एक डेटा एट्रिब्यूट है, जिसका इस्तेमाल करके स्टैंडर्ड एचटीएमएल एलिमेंट के बारे में ज़्यादा जानकारी सेव की जा सकती है. डेटा एट्रिब्यूट को कुछ भी नाम दिया जा सकता है, बशर्ते वह "data-" से शुरू होता हो.

src के बिना iframe लोड नहीं होगा.

दूसरा चरण: वीडियो को लेज़ी-लोड करने के लिए इंटरसेक्शन ऑब्ज़र्वर का इस्तेमाल करना

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

शुरू करने के लिए, एक नई फ़ाइल बनाएं और उसे lazy-load.js नाम दें:

  • नई फ़ाइल पर क्लिक करें और उसे कोई नाम दें.
  • यह फ़ाइल जोड़ें पर क्लिक करें.

अपने दस्तावेज़ के सबसे ऊपरी हिस्से में स्क्रिप्ट टैग जोड़ें:

 <script src="/lazy-load.js" defer></script>

lazy-load.js में, एक नया IntersectionObserver बनाएं और उसे चलाने के लिए, कॉलबैक फ़ंक्शन पास करें:

// create a new Intersection Observer
let observer = new IntersectionObserver(callback);

अब observer को observe तरीके में एक तर्क के तौर पर पास करके, देखने के लिए एक टारगेट एलिमेंट (इस मामले में वीडियो iframe) दें:

// the element that you want to watch
const element = document.querySelector('iframe');

// register the element with the observe method
observer.observe(element);

callback को IntersectionObserverEntry ऑब्जेक्ट और IntersectionObserver ऑब्जेक्ट की सूची मिलती है. हर एंट्री में एक target एलिमेंट और ऐसी प्रॉपर्टी होती हैं जो डिवाइस के डाइमेंशन, पोज़िशन, व्यूपोर्ट में उसके डाले जाने का समय वगैरह की जानकारी देती हैं. IntersectionObserverEntry की एक प्रॉपर्टी isIntersecting है. यह एक बूलियन वैल्यू है, जो एलिमेंट के व्यूपोर्ट में आने पर true के बराबर होती है.

इस उदाहरण में, target, iframe है. जब target व्यूपोर्ट में आता है, तो isIntersecting true के बराबर होता है. इसे काम में देखने के लिए, callback को नीचे दिए गए फ़ंक्शन से बदलें:

let observer = new IntersectionObserver(callback);
let observer = new IntersectionObserver(function(entries, observer) {
    entries.forEach(entry => {
      console.log(entry.target);
      console.log(entry.isIntersecting);
    });
  });
  1. साइट की झलक देखने के लिए, ऐप्लिकेशन देखें दबाएं. इसके बाद, फ़ुलस्क्रीन फ़ुलस्क्रीन दबाएं.
  2. DevTools खोलने के लिए, `Control+Shift+J` (या Mac पर `Command+Option+J`) दबाएं.
  3. कंसोल टैब पर क्लिक करें.

ऊपर और नीचे स्क्रोल करने की कोशिश करें. आपको isIntersecting की वैल्यू में हुए बदलाव और कंसोल में लॉग किए गए टारगेट एलिमेंट दिखेंगे.

जब उपयोगकर्ता वीडियो स्क्रोल करके अपनी पोज़िशन पर स्क्रोल करे, तब वीडियो लोड करने के लिए, loadElement फ़ंक्शन चलाने के लिए, शर्त के तौर पर isIntersecting का इस्तेमाल करें. इससे, iframe एलिमेंट के data-src से वैल्यू मिलती है और यह उसे iframe एलिमेंट के src एट्रिब्यूट के तौर पर सेट करती है. ऐसा करने से वीडियो लोड हो जाता है. इसके बाद, वीडियो लोड होने के बाद, टारगेट एलिमेंट देखना बंद करने के लिए, observer पर unobserve तरीके को कॉल करें:

let observer = new IntersectionObserver(function (entries, observer) {
  entries.forEach(entry => {
    console.log(entry.target);
    console.log(entry.isIntersecting);
  });
});
    if (entry.isIntersecting) {
      // do this when the element enters the viewport
      loadElement(entry.target);
      // stop watching
      observer.unobserve(entry.target);
    }
  });
});

function loadElement(element) {
  const src = element.getAttribute('data-src');
  element.src = src;
}

तीसरा चरण: परफ़ॉर्मेंस का फिर से आकलन करना

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

अब पेज पर नीचे स्क्रोल करें और नेटवर्क पैनल पर नज़र रखें. वीडियो पर जाने के बाद, आपको दिखेगा कि पेज दूसरे अनुरोधों को ट्रिगर करता है.

ज़रूरी ऑरिजिन से पहले से कनेक्ट करें

आपने गैर-ज़रूरी JavaScript को टाल दिया है और YouTube के अनुरोधों को लेज़ी लोड किया है. इसलिए, अब तीसरे पक्ष के बाकी कॉन्टेंट को ऑप्टिमाइज़ करने का समय है.

किसी लिंक में rel=preconnect एट्रिब्यूट जोड़ने से, ब्राउज़र को संसाधन के लिए अनुरोध करने से पहले ही किसी डोमेन से कनेक्ट करने के लिए कहा जाता है. इस एट्रिब्यूट का इस्तेमाल, उन ऑरिजिन पर सबसे अच्छी तरह किया जाता है जो पेज के लिए ज़रूरी संसाधन उपलब्ध कराते हैं.

Preconnect के लिए ज़रूरी ऑरिजिन में सुझाए गए पहले चरण में आपने लाइटहाउस ऑडिट चलाया है. इसे staticxx.facebook.com और youtube.com से शुरुआती कनेक्शन के तौर पर जोड़कर, करीब 400 मि॰से॰ की बचत की जा सकती है:

हाइलाइट किए गए staticxx.facebook.com डोमेन के साथ, ज़रूरी ऑरिजिन ऑडिट से पहले से कनेक्ट करें.

YouTube वीडियो अब लेज़ी लोड हो चुका है. इसलिए, सोशल मीडिया शेयर करने वाले विजेट का सोर्स सिर्फ़ staticxx.facebook.com ही रह जाएगा. इस डोमेन के साथ शुरुआती कनेक्शन बनाना, दस्तावेज़ के <head> में <link> टैग जोड़ने जितना आसान है:

  <link rel="preconnect" href="https://staticxx.facebook.com">

परफ़ॉर्मेंस का फिर से आकलन करना

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

लाइटहाउस ऑडिट में 1 सेकंड का एफ़सीपी और 99 परफ़ॉर्मेंस स्कोर दिखाया गया है.