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

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

  • स्क्रिप्ट लोड होने में लगने वाले समय को कम करना

  • अहम नहीं होने वाले रिसॉर्स को लेज़ी लोड करना

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

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

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

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

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

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

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

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

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

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

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

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

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

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

तीसरे पक्ष की JavaScript को बाद में लोड करना

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

रेंडर ब्लॉक करने वाले संसाधनों को हटाने से जुड़े ऑडिट का स्क्रीनशॉट, जिसमें d3.v3.min.js स्क्रिप्ट को हाइलाइट किया गया है.

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

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

<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. थ्रॉटल करने की सुविधा ड्रॉपडाउन मेन्यू में, फास्ट 3G चुनें.
  6. पेज को फिर से लोड करें.

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

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

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

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

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

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

नई क्रम से लगाने की सुविधा से पता चलता है कि Google Domains के लिए अन्य अनुरोध भी हैं. 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 लोड नहीं होगा.

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

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

शुरू करने के लिए, एक नई फ़ाइल बनाएं और उसका नाम 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 को देखने के लिए कोई टारगेट एलिमेंट दें (इस मामले में वीडियो iframe). इसके लिए, observe तरीके में इसे आर्ग्युमेंट के तौर पर पास करें:

// 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 एट्रिब्यूट जोड़ने से, ब्राउज़र को उस संसाधन का अनुरोध करने से पहले, डोमेन से कनेक्शन बनाने के लिए कहा जाता है. इस एट्रिब्यूट का इस्तेमाल उन ऑरिजिन के लिए सबसे अच्छा होता है जो ऐसे रिसॉर्स उपलब्ध कराते हैं जिनकी ज़रूरत पेज को है.

ज़रूरी ऑरिजिन के साथ पहले से कनेक्शन बनाने के पहले चरण में चलाए गए Lighthouse ऑडिट से पता चला है कि staticxx.facebook.com और youtube.com से पहले से कनेक्शन बनाकर, करीब 400 मिलीसेकंड बचाए जा सकते हैं:

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

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

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

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

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

लाइटहाउस ऑडिट, जिसमें एफ़सीपी एक सेकंड और परफ़ॉर्मेंस स्कोर 99 है.