नेक्स्ट पेंट के इंटरैक्शन को मेज़र करना (आईएनपी)

1. परिचय

यह एक इंटरैक्टिव कोडलैब है. इसमें web-vitals लाइब्रेरी का इस्तेमाल करके, पेज के रिस्पॉन्स में लगने वाला समय (आईएनपी) मेज़र करने का तरीका बताया गया है.

ज़रूरी शर्तें

आपको क्या सीखने को मिलेगा

  • अपने पेज में web-vitals लाइब्रेरी जोड़ने और उसके एट्रिब्यूशन डेटा का इस्तेमाल करने का तरीका.
  • एट्रिब्यूशन डेटा का इस्तेमाल करके, यह पता लगाएं कि आईएनपी को कहां और कैसे बेहतर बनाया जा सकता है.

आपको किस चीज़ की ज़रूरत होगी

  • ऐसा कंप्यूटर जिसमें GitHub से कोड क्लोन करने और npm कमांड चलाने की सुविधा हो.
  • टेक्स्ट एडिटर.
  • सभी इंटरैक्शन मेज़रमेंट के काम करने के लिए, Chrome का नया वर्शन.

2. सेट अप करें

कोड पाना और उसे लागू करना

यह कोड, web-vitals-codelabs रिपॉज़िटरी में मौजूद है.

  1. अपने टर्मिनल में रिपॉज़िटरी को क्लोन करें: git clone https://github.com/GoogleChromeLabs/web-vitals-codelabs.git.
  2. क्लोन की गई डायरेक्ट्री में जाएं: cd web-vitals-codelabs/measuring-inp.
  3. डिपेंडेंसी इंस्टॉल करें: npm ci.
  4. वेब सर्वर शुरू करें: npm run start.
  5. अपने ब्राउज़र में http://localhost:8080/ पर जाएं.

पेज को आज़माएँ

यह कोडलैब, INP से जुड़ी संभावित समस्याओं के बारे में जानने के लिए, Gastropodicon (घोंघे की शारीरिक बनावट के बारे में जानकारी देने वाली लोकप्रिय साइट) का इस्तेमाल करता है.

Gastropodicon के डेमो पेज का स्क्रीनशॉट

पेज के साथ इंटरैक्ट करके देखें कि कौनसे इंटरैक्शन धीमे हैं.

3. Chrome DevTools के बारे में जानकारी

DevTools कोज़्यादा टूल > डेवलपर टूल मेन्यू से खोलें. इसके लिए, पेज पर राइट क्लिक करके जांच करें को चुनें या कीबोर्ड शॉर्टकट का इस्तेमाल करें.

इस कोडलैब में, हम परफ़ॉर्मेंस पैनल और कंसोल, दोनों का इस्तेमाल करेंगे. DevTools में सबसे ऊपर मौजूद टैब में जाकर, इनके बीच कभी भी स्विच किया जा सकता है.

  • आईएनपी से जुड़ी समस्याएं अक्सर मोबाइल डिवाइसों पर होती हैं. इसलिए, मोबाइल डिसप्ले इम्यूलेशन पर स्विच करें.
  • अगर डेस्कटॉप या लैपटॉप पर टेस्टिंग की जा रही है, तो परफ़ॉर्मेंस, असली मोबाइल डिवाइस की तुलना में काफ़ी बेहतर होगी. परफ़ॉर्मेंस को ज़्यादा बेहतर तरीके से देखने के लिए, परफ़ॉर्मेंस पैनल में सबसे ऊपर दाईं ओर मौजूद गियर आइकॉन पर क्लिक करें. इसके बाद, CPU 4x slowdown को चुनें.

ऐप्लिकेशन के साथ-साथ DevTools के परफ़ॉर्मेंस पैनल का स्क्रीनशॉट. इसमें सीपीयू की स्पीड को चार गुना धीमा करने का विकल्प चुना गया है

4. web-vitals इंस्टॉल करना

web-vitals एक JavaScript लाइब्रेरी है. इसका इस्तेमाल, वेबसाइट की परफ़ॉर्मेंस की जानकारी देने वाली उन मेट्रिक को मेज़र करने के लिए किया जाता है जो उपयोगकर्ताओं को दिखती हैं. इस लाइब्रेरी का इस्तेमाल करके, उन वैल्यू को कैप्चर किया जा सकता है. इसके बाद, उन्हें विश्लेषण के लिए Analytics के एंडपॉइंट पर भेजा जा सकता है. इससे हमें यह पता लगाने में मदद मिलती है कि धीमे इंटरैक्शन कब और कहां होते हैं.

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

यह कोडलैब, npm से इंस्टॉल होगा और स्क्रिप्ट को सीधे तौर पर लोड करेगा, ताकि किसी खास बिल्ड प्रोसेस में न जाना पड़े.

web-vitals के दो वर्शन उपलब्ध हैं:

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

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

npm install -D web-vitals चलाकर, प्रोजेक्ट के devDependencies में web-vitals जोड़ें

पेज पर web-vitals जोड़ें:

स्क्रिप्ट के एट्रिब्यूशन वर्शन को index.html के सबसे नीचे जोड़ें और नतीजों को कंसोल में लॉग करें:

<script type="module">
  import {onINP} from './node_modules/web-vitals/dist/web-vitals.attribution.js';

  onINP(console.log);
</script>

इसे आज़माएं

कंसोल खुला रखकर, पेज के साथ फिर से इंटरैक्ट करने की कोशिश करें. पेज पर क्लिक करने पर, कुछ भी लॉग नहीं किया जाता!

आईएनपी को किसी पेज के पूरे लाइफ़साइकल के दौरान मेज़र किया जाता है. इसलिए, डिफ़ॉल्ट रूप से web-vitals, उपयोगकर्ता के पेज छोड़ने या बंद करने तक आईएनपी की रिपोर्ट नहीं करता है. यह Analytics जैसे टूल के लिए बीकन भेजने का सबसे सही तरीका है. हालांकि, इंटरैक्टिव तरीके से डीबग करने के लिए यह तरीका सही नहीं है.

web-vitals, ज़्यादा जानकारी वाली रिपोर्टिंग के लिए reportAllChanges विकल्प देता है. इस सुविधा के चालू होने पर, हर इंटरैक्शन की रिपोर्ट नहीं की जाती. हालांकि, जब भी कोई इंटरैक्शन पिछले इंटरैक्शन से ज़्यादा समय लेता है, तो उसकी रिपोर्ट की जाती है.

स्क्रिप्ट में विकल्प जोड़ने की कोशिश करें और पेज के साथ फिर से इंटरैक्ट करें:

<script type="module">
  import {onINP} from './node_modules/web-vitals/dist/web-vitals.attribution.js';

  onINP(console.log, {reportAllChanges: true});
</script>

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

DevTools कंसोल का स्क्रीनशॉट, जिसमें INP मैसेज को प्रिंट किया गया है

5. एट्रिब्यूशन में क्या-क्या शामिल होता है?

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

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

(डेमो) कुकी स्वीकार करने के लिए, हां पर क्लिक करें. अब DevTools कंसोल में लॉग किए गए INP डेटा को देखें.

DevTools कंसोल में लॉग किया गया INP डेटा ऑब्जेक्ट

यह टॉप-लेवल की जानकारी, स्टैंडर्ड और एट्रिब्यूशन वेब-वाइटल, दोनों के बिल्ड में उपलब्ध है:

{
  name: 'INP',
  value: 344,
  rating: 'needs-improvement',
  entries: [...],
  id: 'v4-1715732159298-8028729544485',
  navigationType: 'reload',
  attribution: {...},
}

उपयोगकर्ता के क्लिक करने से लेकर अगले पेंट तक का समय 344 मिलीसेकंड था. यह "सुधार की ज़रूरत है" वाले आईएनपी के दायरे में आता है. entries ऐरे में, इस इंटरैक्शन से जुड़ी सभी PerformanceEntry वैल्यू मौजूद हैं. इस मामले में, सिर्फ़ एक क्लिक इवेंट है.

हालांकि, इस दौरान क्या हो रहा है, यह जानने के लिए हमें attribution प्रॉपर्टी में सबसे ज़्यादा दिलचस्पी है. एट्रिब्यूशन डेटा बनाने के लिए, web-vitals यह पता लगाता है कि कौनसी लॉन्ग ऐनिमेशन फ़्रेम (एलओएएफ़), क्लिक इवेंट के साथ ओवरलैप होती है. इसके बाद, LoAF इस बारे में ज़्यादा जानकारी दे सकता है कि उस फ़्रेम के दौरान कितना समय किस काम में लगा. जैसे, स्क्रिप्ट चलाने में, requestAnimationFrame कॉलबैक, स्टाइल, और लेआउट में कितना समय लगा.

ज़्यादा जानकारी देखने के लिए, attribution प्रॉपर्टी को बड़ा करें. डेटा ज़्यादा बेहतर होता है.

attribution: {
  interactionTargetElement: Element,
  interactionTarget: '#confirm',
  interactionType: 'pointer',

  inputDelay: 27,
  processingDuration: 295.6,
  presentationDelay: 21.4,

  processedEventEntries: [...],
  longAnimationFrameEntries: [...],
}

सबसे पहले, यह जानकारी होती है कि किस कॉन्टेंट के साथ इंटरैक्ट किया गया:

  • interactionTargetElement: उस एलिमेंट का लाइव रेफ़रंस जिसके साथ इंटरैक्ट किया गया था. हालांकि, ऐसा तब होता है, जब एलिमेंट को डीओएम से न हटाया गया हो.
  • interactionTarget: पेज में मौजूद एलिमेंट को ढूंढने के लिए सिलेक्टर.

इसके बाद, समय को बड़े लेवल पर बांटा गया है:

  • inputDelay: यह वह समय होता है जब उपयोगकर्ता ने इंटरैक्शन शुरू किया था (उदाहरण के लिए, माउस पर क्लिक किया था) और जब उस इंटरैक्शन के लिए इवेंट लिसनर ने काम करना शुरू किया था. इस मामले में, सीपीयू थ्रॉटलिंग चालू होने पर भी इनपुट में सिर्फ़ 27 मिलीसेकंड की देरी हुई.
  • processingDuration: इवेंट लिसनर को पूरा होने में लगने वाला समय. अक्सर, पेजों पर एक इवेंट के लिए कई लिसनर होते हैं. उदाहरण के लिए, pointerdown, pointerup, और click. अगर ये सभी एक ही ऐनिमेशन फ़्रेम में चलते हैं, तो इन्हें इस समय में शामिल कर दिया जाएगा. इस मामले में, प्रोसेस होने में 295.6 मिलीसेकंड लगते हैं. यह INP का ज़्यादातर समय होता है.
  • presentationDelay: यह इवेंट लिसनर के पूरा होने से लेकर, ब्राउज़र के अगले फ़्रेम को पेंट करने तक का समय होता है. इस मामले में, 21.4 मिलीसेकंड.

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

थोड़ी और जानकारी के लिए, टॉप-लेवल INP entries ऐरे में सिर्फ़ एक इवेंट के मुकाबले, processedEventEntries में पांच इवेंट शामिल हैं. इन दोनों में क्या अंतर है?

processedEventEntries: [
  {
    name: 'mouseover',
    entryType: 'event',
    startTime: 1801.6,
    duration: 344,
    processingStart: 1825.3,
    processingEnd: 1825.3,
    cancelable: true
  },
  {
    name: 'mousedown',
    entryType: 'event',
    startTime: 1801.6,
    duration: 344,
    processingStart: 1825.3,
    processingEnd: 1825.3,
    cancelable: true
  },
  {name: 'mousedown', ...},
  {name: 'mouseup', ...},
  {name: 'click', ...},
],

सबसे ऊपर वाली एंट्री, the INP इवेंट है. इस मामले में, यह क्लिक है. एट्रिब्यूशन processedEventEntries, वे सभी इवेंट हैं जिन्हें एक ही फ़्रेम के दौरान प्रोसेस किया गया था. ध्यान दें कि इसमें क्लिक इवेंट के साथ-साथ mouseover और mousedown जैसे अन्य इवेंट भी शामिल हैं. अगर ये अन्य इवेंट भी धीमे थे, तो इनके बारे में जानना ज़रूरी हो सकता है. ऐसा इसलिए, क्योंकि इन सभी इवेंट की वजह से ही रिस्पॉन्स मिलने में समय लगा.

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

longAnimationFrameEntries

LoAF एंट्री को बड़ा करना:

longAnimationFrameEntries: [{
  name: 'long-animation-frame',
  startTime: 1823,
  duration: 319,

  renderStart: 2139.5,
  styleAndLayoutStart: 2139.7,
  firstUIEventTimestamp: 1801.6,
  blockingDuration: 268,

  scripts: [{...}]
}],

यहां कई काम की वैल्यू मौजूद हैं. जैसे, स्टाइलिंग में बिताए गए समय की जानकारी. Long Animation Frames API लेख में, इन प्रॉपर्टी के बारे में ज़्यादा जानकारी दी गई है. फ़िलहाल, हमारा मुख्य फ़ोकस scripts प्रॉपर्टी पर है. इसमें ऐसी एंट्री होती हैं जो लंबे समय तक चलने वाले फ़्रेम के लिए ज़िम्मेदार स्क्रिप्ट के बारे में जानकारी देती हैं:

scripts: [{
  name: 'script',
  invoker: 'BUTTON#confirm.onclick',
  invokerType: 'event-listener',

  startTime: 1828.6,
  executionStart: 1828.6,
  duration: 294,

  sourceURL: 'http://localhost:8080/third-party/cmp.js',
  sourceFunctionName: '',
  sourceCharPosition: 1144
}]

इस मामले में, हम बता सकते हैं कि ज़्यादातर समय एक ही event-listener में बिताया गया. इसे BUTTON#confirm.onclick पर शुरू किया गया था. हम स्क्रिप्ट सोर्स का यूआरएल और फ़ंक्शन को तय करने वाली वर्ण की पोज़िशन भी देख सकते हैं!

सीखने लायक अहम बातें

इस एट्रिब्यूशन डेटा से, इस मामले के बारे में क्या पता लगाया जा सकता है?

  • यह इंटरैक्शन, button#confirm एलिमेंट पर क्लिक करने से ट्रिगर हुआ था. यह एलिमेंट, attribution.interactionTarget और स्क्रिप्ट एट्रिब्यूशन एंट्री की invoker प्रॉपर्टी से मिला था.
  • ज़्यादातर समय, इवेंट लिसनर को एक्ज़ीक्यूट करने में लगा. यह समय, कुल मेट्रिक value की तुलना में attribution.processingDuration से ज़्यादा है.
  • इवेंट लिसनर के धीमे कोड की शुरुआत, third-party/cmp.js में तय किए गए क्लिक लिसनर (scripts.sourceURL से) से होती है.

यह डेटा, हमें यह जानने के लिए काफ़ी है कि हमें कहां ऑप्टिमाइज़ेशन करने की ज़रूरत है!

6. एक से ज़्यादा इवेंट लिसनर

पेज को रीफ़्रेश करें, ताकि DevTools कंसोल साफ़ हो जाए और कुकी के लिए सहमति लेने से जुड़ा इंटरैक्शन, सबसे लंबा इंटरैक्शन न रहे.

खोज बॉक्स में लिखना शुरू करें. एट्रिब्यूशन डेटा से क्या पता चलता है? आपको क्या लगता है कि क्या हो रहा है?

एट्रिब्यूशन डेटा

सबसे पहले, डेमो की जांच करने के एक उदाहरण की खास जानकारी:

{
  name: 'INP',
  value: 1072,
  rating: 'poor',
  attribution: {
    interactionTargetElement: Element,
    interactionTarget: '#search-terms',
    interactionType: 'keyboard',

    inputDelay: 3.3,
    processingDuration: 1060.6,
    presentationDelay: 8.1,

    processedEventEntries: [...],
    longAnimationFrameEntries: [...],
  }
}

यह input#search-terms एलिमेंट के साथ कीबोर्ड इंटरैक्शन से मिली आईएनपी की खराब वैल्यू है. इसमें सीपीयू थ्रॉटलिंग चालू है. ज़्यादातर समय, यानी कि 1,072 मिलीसेकंड के कुल आईएनपी में से 1,061 मिलीसेकंड, प्रोसेस करने में लगा.

हालांकि, scripts की एंट्री ज़्यादा दिलचस्प हैं.

लेआउट थ्रैशिंग

scripts अरे की पहली एंट्री से हमें कुछ अहम जानकारी मिलती है:

scripts: [{
  name: 'script',
  invoker: 'BUTTON#confirm.onclick',
  invokerType: 'event-listener',

  startTime: 4875.6,
  executionStart: 4875.6,
  duration: 497,
  forcedStyleAndLayoutDuration: 388,

  sourceURL: 'http://localhost:8080/js/index.js',
  sourceFunctionName: 'handleSearch',
  sourceCharPosition: 940
},
...]

प्रोसेसिंग में लगने वाला ज़्यादातर समय, इस स्क्रिप्ट को एक्ज़ीक्यूट करने के दौरान लगता है. यह एक input लिसनर है (इनवॉकर INPUT#search-terms.oninput है). फ़ंक्शन का नाम (handleSearch) दिया गया है. साथ ही, index.js सोर्स फ़ाइल में वर्ण की पोज़िशन भी दी गई है.

हालांकि, एक नई प्रॉपर्टी उपलब्ध है: forcedStyleAndLayoutDuration. यह स्क्रिप्ट को शुरू करने में लगा समय है. इस दौरान, ब्राउज़र को पेज का लेआउट फिर से तय करना पड़ा. दूसरे शब्दों में कहें, तो इस इवेंट लिसनर को एक्ज़ीक्यूट करने में लगे कुल समय का 78% समय, लेआउट थ्रैशिंग में लगा. यानी, 497 मिलीसेकंड में से 388 मिलीसेकंड.

इस समस्या को ठीक करना सबसे ज़रूरी है.

बार-बार सुनने वाले लोग

अलग-अलग तौर पर, अगली दो स्क्रिप्ट एंट्री में कुछ खास नहीं है:

scripts: [...,
{
  name: 'script',
  invoker: '#document.onkeyup',
  invokerType: 'event-listener',

  startTime: 5375.3,
  executionStart: 5375.3,
  duration: 124,

  sourceURL: 'http://localhost:8080/js/index.js',
  sourceFunctionName: '',
  sourceCharPosition: 1526,
},
{
  name: 'script',
  invoker: '#document.onkeyup',
  invokerType: 'event-listener',

  startTime: 5673.9,
  executionStart: 5673.9,
  duration: 95,

  sourceURL: 'http://localhost:8080/js/index.js',
  sourceFunctionName: '',
  sourceCharPosition: 1526
}]

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

हालांकि, हैरानी की बात यह है कि दोनों एक ही सोर्स फ़ाइल और वर्ण की पोज़िशन से हैं.

ब्राउज़र ने एक ही ऐनिमेशन फ़्रेम में कई कीप्रेस प्रोसेस किए. इस वजह से, कुछ भी पेंट किए जाने से पहले यह इवेंट लिसनर दो बार चला!

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

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

7. इनपुट में देरी

इनपुट डिले की वजह यह होती है कि मुख्य थ्रेड व्यस्त है. इनपुट डिले का मतलब है कि उपयोगकर्ता के इंटरैक्ट करने से लेकर, इवेंट लिसनर के इंटरैक्शन को प्रोसेस करने के बीच लगने वाला समय. ऐसा कई वजहों से हो सकता है:

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

डेमो पेज में एक सीक्रेट सुविधा है. अगर पेज के सबसे ऊपर मौजूद घोंघे के लोगो पर क्लिक किया जाता है, तो वह ऐनिमेशन करने लगेगा. साथ ही, मेन थ्रेड पर JavaScript से जुड़े कुछ मुश्किल काम करने लगेगा.

  • ऐनिमेशन शुरू करने के लिए, घोंघे के लोगो पर क्लिक करें.
  • JavaScript टास्क तब ट्रिगर होते हैं, जब स्नेल बाउंस के सबसे निचले हिस्से में होता है. बाउंस होने से पहले, पेज के साथ इंटरैक्ट करने की कोशिश करें. देखें कि इससे आईएनपी कितना बढ़ जाता है.

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

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

यहां सिर्फ़ खोज बॉक्स पर फ़ोकस करने के दौरान, स्नेल बाउंस से मिले एट्रिब्यूशन का उदाहरण दिया गया है:

{
  name: 'INP',
  value: 728,
  rating: 'poor',

  attribution: {
    interactionTargetElement: Element,
    interactionTarget: '#search-terms',
    interactionType: 'pointer',

    inputDelay: 702.3,
    processingDuration: 4.9,
    presentationDelay: 20.8,

    longAnimationFrameEntries: [{
      name: 'long-animation-frame',
      startTime: 2064.8,
      duration: 790,

      renderStart: 2065,
      styleAndLayoutStart: 2854.2,
      firstUIEventTimestamp: 0,
      blockingDuration: 740,

      scripts: [{...}]
    }]
  }
}

अनुमान के मुताबिक, इवेंट लिसनर ने तेज़ी से काम किया. इसमें प्रोसेस होने में 4.9 मिलीसेकंड लगे. साथ ही, ज़्यादातर खराब इंटरैक्शन में इनपुट में देरी हुई. इसमें कुल 728 मिलीसेकंड में से 702.3 मिलीसेकंड लगे.

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

LoAF स्क्रिप्ट की ये एंट्री, आपकी मदद कर सकती हैं:

scripts: [{
  name: 'script',
  invoker: 'SPAN.onanimationiteration',
  invokerType: 'event-listener',

  startTime: 2065,
  executionStart: 2065,
  duration: 788,

  sourceURL: 'http://localhost:8080/js/index.js',
  sourceFunctionName: 'cryptodaphneCoinHandler',
  sourceCharPosition: 1831
}]

भले ही, इस फ़ंक्शन का इंटरैक्शन से कोई लेना-देना नहीं था, लेकिन इससे ऐनिमेशन फ़्रेम की स्पीड कम हो गई. इसलिए, इसे LoAF डेटा में शामिल किया गया है. यह डेटा, इंटरैक्शन इवेंट के साथ जोड़ा जाता है.

इससे हमें यह पता चलता है कि इंटरैक्शन प्रोसेसिंग में देरी करने वाले फ़ंक्शन को कैसे ट्रिगर किया गया (animationiteration लिसनर के ज़रिए), इसके लिए कौनसा फ़ंक्शन ज़िम्मेदार था, और यह हमारी सोर्स फ़ाइलों में कहां मौजूद था.

8. अपडेट दिखने में देरी होना: जब कोई अपडेट नहीं दिखता है

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

आईएनपी वैल्यू को फिर से रीसेट करने के लिए, पेज को रीफ़्रेश करें. इसके बाद, हैमबर्गर मेन्यू खोलें. इसे खोलने पर, कुछ समय के लिए यह रुक जाता है.

यह कैसा दिखता है?

{
  name: 'INP',
  value: 376,
  rating: 'needs-improvement',
  delta: 352,

  attribution: {
    interactionTarget: '#sidenav-button>svg',
    interactionType: 'pointer',

    inputDelay: 12.8,
    processingDuration: 14.7,
    presentationDelay: 348.5,

    longAnimationFrameEntries: [{
      name: 'long-animation-frame',
      startTime: 651,
      duration: 365,

      renderStart: 673.2,
      styleAndLayoutStart: 1004.3,
      firstUIEventTimestamp: 138.6,
      blockingDuration: 315,

      scripts: [{...}]
    }]
  }
}

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

scripts: [{
  entryType: 'script',
  invoker: 'FrameRequestCallback',
  invokerType: 'user-callback',

  startTime: 673.8,
  executionStart: 673.8,
  duration: 330,

  sourceURL: 'http://localhost:8080/js/side-nav.js',
  sourceFunctionName: '',
  sourceCharPosition: 1193,
}]

scripts कलेक्शन में मौजूद एक एंट्री से पता चलता है कि FrameRequestCallback से मिले user-callback में समय बिताया गया है. इस बार, प्रज़ेंटेशन में देरी requestAnimationFrame कॉलबैक की वजह से हो रही है.

9. नतीजा

फ़ील्ड डेटा को एग्रीगेट करना

यह ध्यान रखना ज़रूरी है कि एक पेज लोड से, एक INP एट्रिब्यूशन एंट्री देखने पर यह सब आसान हो जाता है. फ़ील्ड डेटा के आधार पर INP को डीबग करने के लिए, इस डेटा को कैसे इकट्ठा किया जा सकता है? काम की ज़्यादा जानकारी होने की वजह से, इसे समझना मुश्किल हो जाता है.

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

इसके बजाय, आपको अपने ऐप्लिकेशन के बारे में सोचना होगा, ताकि यह तय किया जा सके कि कौनसा डेटा सबसे ज़्यादा काम का है और डेटा को कैसे एग्रीगेट किया जा सकता है. उदाहरण के लिए, एट्रिब्यूशन डेटा को वापस बीकन करने से पहले, web-vitals सिलेक्टर को अपने आइडेंटिफ़ायर से बदला जा सकता है. यह आइडेंटिफ़ायर, टारगेट के कॉम्पोनेंट या टारगेट की ARIA भूमिकाओं के आधार पर तय किया जाता है.

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

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

हर जगह क्रेडिट देना!

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

अब किसी भी साइट पर INP एट्रिब्यूशन डेटा का इस्तेमाल किया जा सकता है!

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

const script = document.createElement('script');
script.src = 'https://unpkg.com/web-vitals@4/dist/web-vitals.attribution.iife.js';
script.onload = function () {
  webVitals.onINP(console.log, {reportAllChanges: true});
};
document.head.appendChild(script);

ज़्यादा जानें