1. परिचय
यह एक इंटरैक्टिव कोडलैब है. इसमें web-vitals लाइब्रेरी का इस्तेमाल करके, पेज के रिस्पॉन्स में लगने वाला समय (आईएनपी) मेज़र करने का तरीका बताया गया है.
ज़रूरी शर्तें
- एचटीएमएल और JavaScript डेवलपमेंट की जानकारी.
- सुझाया गया तरीका: web.dev पर INP मेट्रिक से जुड़ा दस्तावेज़ पढ़ें.
आपको क्या सीखने को मिलेगा
- अपने पेज में
web-vitalsलाइब्रेरी जोड़ने और उसके एट्रिब्यूशन डेटा का इस्तेमाल करने का तरीका. - एट्रिब्यूशन डेटा का इस्तेमाल करके, यह पता लगाएं कि आईएनपी को कहां और कैसे बेहतर बनाया जा सकता है.
आपको इन चीज़ों की ज़रूरत होगी
- ऐसा कंप्यूटर जिसमें GitHub से कोड क्लोन करने और npm कमांड चलाने की सुविधा हो.
- टेक्स्ट एडिटर.
- सभी इंटरैक्शन मेज़रमेंट के काम करने के लिए, Chrome का नया वर्शन.
2. सेट अप करें
कोड पाना और उसे लागू करना
यह कोड, web-vitals-codelabs रिपॉज़िटरी में मौजूद है.
- अपने टर्मिनल में रिपॉज़िटरी को क्लोन करें:
git clone https://github.com/GoogleChromeLabs/web-vitals-codelabs.git. - क्लोन की गई डायरेक्ट्री में जाएं:
cd web-vitals-codelabs/measuring-inp. - डिपेंडेंसी इंस्टॉल करें:
npm ci. - वेब सर्वर शुरू करें:
npm run start. - अपने ब्राउज़र में http://localhost:8080/ पर जाएं.
पेज को आज़माएँ
यह कोडलैब, INP से जुड़ी संभावित समस्याओं के बारे में जानने के लिए, Gastropodicon (घोंघे की शारीरिक बनावट के बारे में जानकारी देने वाली लोकप्रिय साइट) का इस्तेमाल करता है.

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

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

5. एट्रिब्यूशन में क्या-क्या शामिल होता है?
आइए, सबसे पहले उस इंटरैक्शन के बारे में बात करते हैं जो ज़्यादातर उपयोगकर्ता पेज पर करते हैं. यह इंटरैक्शन, कुकी के लिए सहमति देने वाला डायलॉग बॉक्स होता है.
कई पेजों में ऐसी स्क्रिप्ट होती हैं जिनके लिए, उपयोगकर्ता के कुकी स्वीकार करने पर कुकी को सिंक्रोनस तरीके से ट्रिगर करना ज़रूरी होता है. इससे क्लिक करने पर, इंटरैक्शन धीरे-धीरे होता है. यहां भी ऐसा ही होता है.
(डेमो) कुकी स्वीकार करने के लिए, हां पर क्लिक करें. अब DevTools कंसोल में लॉग किए गए आईएनपी डेटा को देखें.

यह टॉप-लेवल की जानकारी, स्टैंडर्ड और एट्रिब्यूशन वेब-वाइटल, दोनों के बिल्ड में उपलब्ध है:
{
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 मिलीसेकंड.
आईएनपी के ये फ़ेज़, यह पता लगाने के लिए अहम सिग्नल हो सकते हैं कि किस चीज़ को ऑप्टिमाइज़ करने की ज़रूरत है. आईएनपी को ऑप्टिमाइज़ करने की गाइड में इस विषय के बारे में ज़्यादा जानकारी दी गई है.
थोड़ा और गहराई से देखें, तो पता चलता है कि processedEventEntries में पांच इवेंट हैं. वहीं, टॉप-लेवल INP entries ऐरे में सिर्फ़ एक इवेंट है. इन दोनों में क्या अंतर है?
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: