1. परिचय
यह एक इंटरैक्टिव कोडलैब है. इसमें web-vitals
लाइब्रेरी का इस्तेमाल करके, इंटरैक्शन टू नेक्स्ट पेंट (आईएनपी) को मेज़र करने का तरीका बताया गया है.
ज़रूरी शर्तें
- एचटीएमएल और JavaScript डेवलपमेंट के बारे में जानकारी.
- हमारा सुझाव है: web.dev INP मेट्रिक का दस्तावेज़ पढ़ें.
आपको क्या सीखने को मिलेगा
- अपने पेज में
web-vitals
लाइब्रेरी जोड़ने और उसके एट्रिब्यूशन डेटा का इस्तेमाल करने का तरीका. - एट्रिब्यूशन डेटा का इस्तेमाल करके, यह पता लगाएं कि INP को कहां और कैसे बेहतर बनाया जा सकता है.
आपको किन चीज़ों की ज़रूरत होगी
- ऐसा कंप्यूटर जिसमें 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/ पर जाएं.
पेज आज़माएं
इस कोडलैब में, Gastropodicon (घोंसले की शारीरिक संरचना के बारे में जानकारी देने वाली लोकप्रिय साइट) का इस्तेमाल करके, INP से जुड़ी संभावित समस्याओं के बारे में बताया गया है.
पेज के साथ इंटरैक्ट करके देखें कि कौनसे इंटरैक्शन धीमे हैं.
3. Chrome DevTools का इस्तेमाल करना
ज़्यादा टूल > डेवलपर टूल मेन्यू से DevTools खोलें. इसके लिए, पेज पर दायां क्लिक करके जांच करें को चुनें या कीबोर्ड शॉर्टकट का इस्तेमाल करें.
इस कोडलैब में, हम परफ़ॉर्मेंस पैनल और कंसोल, दोनों का इस्तेमाल करेंगे. DevTools में सबसे ऊपर मौजूद टैब में जाकर, इनके बीच कभी भी स्विच किया जा सकता है.
- आईएनपी से जुड़ी समस्याएं ज़्यादातर मोबाइल डिवाइसों पर होती हैं. इसलिए, मोबाइल डिसप्ले इम्यूलेशन पर स्विच करें.
- अगर डेस्कटॉप या लैपटॉप पर जांच की जा रही है, तो हो सकता है कि परफ़ॉर्मेंस, असली मोबाइल डिवाइस के मुकाबले काफ़ी बेहतर हो. परफ़ॉर्मेंस के बारे में ज़्यादा जानकारी के लिए, परफ़ॉर्मेंस पैनल में सबसे ऊपर दाईं ओर मौजूद गियर पर क्लिक करें. इसके बाद, सीपीयू की स्पीड चार गुना कम करें को चुनें.
4. वेब-विटल्स इंस्टॉल करना
web-vitals
एक JavaScript लाइब्रेरी है. इसका इस्तेमाल, वेब पर उपयोगकर्ताओं को मिलने वाली वेब वाइटल मेट्रिक को मेज़र करने के लिए किया जाता है. इन वैल्यू को कैप्चर करने के लिए, लाइब्रेरी का इस्तेमाल किया जा सकता है. इसके बाद, बाद में विश्लेषण के लिए उन्हें किसी Analytics एंडपॉइंट पर भेजा जा सकता है. इससे हमें यह पता चलता है कि इंटरैक्शन कब और कहां धीमे होते हैं.
किसी पेज में लाइब्रेरी जोड़ने के कुछ अलग-अलग तरीके हैं. अपनी साइट पर लाइब्रेरी को इंस्टॉल करने का तरीका, इस बात पर निर्भर करेगा कि आपने डिपेंडेंसी, बिल्ड प्रोसेस, और अन्य फ़ैक्टर को कैसे मैनेज किया है. अपने सभी विकल्पों के बारे में जानने के लिए, लाइब्रेरी के दस्तावेज़ ज़रूर देखें.
यह कोडलैब, npm से इंस्टॉल होगा और सीधे स्क्रिप्ट को लोड करेगा, ताकि किसी खास बिल्ड प्रोसेस में न जाना पड़े.
web-vitals
के दो वर्शन इस्तेमाल किए जा सकते हैं:
- अगर आपको पेज लोड होने पर, वेबसाइट की परफ़ॉर्मेंस की अहम जानकारी देने वाली मेट्रिक की वैल्यू ट्रैक करनी है, तो "स्टैंडर्ड" बिल्ड का इस्तेमाल करें.
- "एट्रिब्यूशन" बिल्ड, हर मेट्रिक में अतिरिक्त डीबग जानकारी जोड़ता है, ताकि यह पता लगाया जा सके कि किसी मेट्रिक में वैल्यू क्यों दिखती है.
इस कोडलैब में INP को मेज़र करने के लिए, हमें एट्रिब्यूशन बिल्ड चाहिए.
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
, तब तक आईएनपी की रिपोर्ट नहीं करता, जब तक उपयोगकर्ता पेज को नहीं छोड़ता या बंद नहीं करता. आंकड़ों जैसी किसी चीज़ के लिए, यह बीकन करने का सबसे सही तरीका है. हालांकि, इंटरैक्टिव तरीके से डीबग करने के लिए, यह सही नहीं है.
web-vitals
, ज़्यादा जानकारी वाली रिपोर्टिंग के लिए reportAllChanges
विकल्प उपलब्ध कराता है. इस सुविधा के चालू होने पर, हर इंटरैक्शन की रिपोर्ट नहीं की जाती. हालांकि, जब भी किसी इंटरैक्शन में पिछले इंटरैक्शन से ज़्यादा समय लगता है, तो उसकी रिपोर्ट की जाती है.
स्क्रिप्ट में विकल्प जोड़कर, पेज के साथ फिर से इंटरैक्ट करने की कोशिश करें:
<script type="module">
import {onINP} from './node_modules/web-vitals/dist/web-vitals.attribution.js';
onINP(console.log, {reportAllChanges: true});
</script>
पेज को रीफ़्रेश करें. अब इंटरैक्शन की जानकारी, Console में रिपोर्ट की जानी चाहिए. साथ ही, जब भी कोई नया इंटरैक्शन सबसे धीमा होगा, तब वह अपडेट हो जाएगा. उदाहरण के लिए, खोज बॉक्स में कुछ लिखकर, इनपुट मिटाएं.
5. एट्रिब्यूशन में क्या होता है?
सबसे पहले, कुकी के लिए सहमति देने वाले डायलॉग बॉक्स से शुरू करते हैं. यह पेज पर उपयोगकर्ताओं के सबसे पहले इंटरैक्शन का हिस्सा होता है.
कई पेजों पर ऐसी स्क्रिप्ट होंगी जिनमें उपयोगकर्ता की ओर से कुकी स्वीकार किए जाने पर, कुकी को एक साथ ट्रिगर करने की ज़रूरत होती है. इस वजह से, क्लिक धीमा हो जाता है. यहां ऐसा ही होता है.
(डेमो) कुकी स्वीकार करने के लिए, हां पर क्लिक करें. इसके बाद, DevTools कंसोल में लॉग किए गए INP डेटा पर एक नज़र डालें.
यह टॉप-लेवल की जानकारी, स्टैंडर्ड और एट्रिब्यूशन वेब-विटल्स, दोनों बिल्ड में उपलब्ध है:
{
name: 'INP',
value: 344,
rating: 'needs-improvement',
entries: [...],
id: 'v4-1715732159298-8028729544485',
navigationType: 'reload',
attribution: {...},
}
उपयोगकर्ता के क्लिक करने से लेकर अगले पेज के पेंट होने में 344 मिलीसेकंड का समय लगा. यह "बेहतर बनाने की ज़रूरत है" आईएनपी है. entries
कलेक्शन में, इस इंटरैक्शन से जुड़ी सभी PerformanceEntry
वैल्यू होती हैं. इस मामले में, सिर्फ़ एक क्लिक इवेंट.
हालांकि, इस दौरान क्या हो रहा है, यह जानने के लिए हमारी सबसे ज़्यादा दिलचस्पी attribution
प्रॉपर्टी में है. एट्रिब्यूशन डेटा बनाने के लिए, web-vitals
यह पता लगाता है कि क्लिक इवेंट के साथ कौनसा लंबा ऐनिमेशन फ़्रेम (LoAF) ओवरलैप होता है. इसके बाद, 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', ...},
],
टॉप-लेवल एंट्री, वह 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: [{...}]
}],
यहां कई काम की वैल्यू मौजूद हैं. जैसे, स्टाइल करने में लगने वाला समय. लंबी अवधि के ऐनिमेशन फ़्रेम एपीआई लेख में, इन प्रॉपर्टी के बारे में ज़्यादा जानकारी दी गई है. फ़िलहाल, हमारी दिलचस्पी मुख्य रूप से 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
}]
इस मामले में, हम यह बता सकते हैं कि ज़्यादातर समय BUTTON#confirm.onclick
पर ट्रिगर किए गए एक event-listener
में बिताया गया था. हम स्क्रिप्ट सोर्स का यूआरएल और फ़ंक्शन तय करने की जगह के वर्ण की स्थिति भी देख सकते हैं!
सीखने लायक अहम बातें
इस एट्रिब्यूशन डेटा से, इस मामले के बारे में क्या पता चलता है?
- इंटरैक्शन,
button#confirm
एलिमेंट (स्क्रिप्ट एट्रिब्यूशन एंट्री परattribution.interactionTarget
औरinvoker
प्रॉपर्टी से) पर क्लिक करके ट्रिगर हुआ था. attribution.processingDuration
सेvalue
मेट्रिक की तुलना में, इवेंट लिसनर को लागू करने में ज़्यादा समय लगा.- स्लो इवेंट लिसनर कोड,
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
एलिमेंट के साथ कीबोर्ड इंटरैक्शन से मिली खराब आईएनपी वैल्यू है. इसमें सीपीयू थ्रॉटलिंग की सुविधा चालू है. कुल 1072 मिलीसेकंड के INP में से 1061 मिलीसेकंड, प्रोसेसिंग में लग गए.
हालांकि, 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
. इस स्क्रिप्ट को शुरू करने में लगने वाला समय, जब ब्राउज़र को पेज को फिर से लेआउट करना पड़ा. दूसरे शब्दों में, इस इवेंट लिसनर को लागू करने में 497 में से 388 मिलीसेकंड का 78% समय, असल में लेआउट थ्रैशिंग में खर्च हुआ.
इसे ठीक करना सबसे ज़रूरी है.
बार-बार सुनने वाले लोग
अगली दो स्क्रिप्ट एंट्री में, अलग-अलग तौर पर कुछ खास नहीं है:
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. इनपुट में देरी
इनपुट में लगने वाले समय की मुख्य वजह यह है कि मुख्य थ्रेड व्यस्त है. यह समय, उपयोगकर्ता के इंटरैक्ट करने से लेकर, इवेंट सुनने वाले को इंटरैक्शन प्रोसेस करने में लगने वाला समय होता है. इसकी कई वजहें हो सकती हैं:
- पेज लोड हो रहा है और मुख्य थ्रेड, DOM को सेट अप करने, पेज को लेआउट और स्टाइल देने, और स्क्रिप्ट का आकलन करने और उन्हें चलाने के शुरुआती काम में व्यस्त है.
- पेज आम तौर पर व्यस्त रहता है. उदाहरण के लिए, कैलकुलेशन, स्क्रिप्ट पर आधारित ऐनिमेशन या विज्ञापन दिखाना.
- पिछले इंटरैक्शन को प्रोसेस होने में इतना समय लगता है कि आने वाले समय में होने वाले इंटरैक्शन में देरी होती है. इस बारे में पिछले उदाहरण में बताया गया है.
डेमो पेज में एक गुप्त सुविधा है. अगर पेज पर सबसे ऊपर मौजूद स्नेल के लोगो पर क्लिक किया जाता है, तो यह ऐनिमेशन शुरू कर देगा और मेन थ्रेड में JavaScript का कुछ ज़्यादा काम करेगा.
- ऐनिमेशन शुरू करने के लिए, स्नेल के लोगो पर क्लिक करें.
- जब स्नेल बाउंस के सबसे नीचे होता है, तब JavaScript टास्क ट्रिगर होते हैं. पेज पर जितना हो सके उतना नीचे तक इंटरैक्ट करें और देखें कि आपके पास कितना ज़्यादा आईएनपी ट्रिगर करने का विकल्प है.
उदाहरण के लिए, अगर आपने कोई दूसरा इवेंट लिसनर ट्रिगर नहीं किया है, तो भी मुख्य थ्रेड के काम की वजह से पेज कुछ समय के लिए काम नहीं करेगा. जैसे, स्नेल बाउंस होने के दौरान, खोज बॉक्स पर क्लिक करके उस पर फ़ोकस करना.
कई पेजों पर, मुख्य थ्रेड का ज़्यादा काम इस तरह से ठीक से नहीं होगा. हालांकि, यह एक अच्छा उदाहरण है, जिसमें यह देखा जा सकता है कि INP एट्रिब्यूशन डेटा में इसकी पहचान कैसे की जा सकती है.
यहां स्नेल बाउंस के दौरान सिर्फ़ खोज बॉक्स पर फ़ोकस करने से जुड़े एट्रिब्यूशन का उदाहरण दिया गया है:
{
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
listener की मदद से), कौनसा फ़ंक्शन ज़िम्मेदार था, और वह हमारी सोर्स फ़ाइलों में कहां मौजूद था.
8. प्रज़ेंटेशन में देरी: जब अपडेट पेंट नहीं होता
प्रज़ेंटेशन में लगने वाला समय, इवेंट के लिसनर के बंद होने से लेकर, ब्राउज़र के स्क्रीन पर नया फ़्रेम पेंट करने तक के समय को मेज़र करता है. इस दौरान, उपयोगकर्ता को विज़ुअल फ़ीडबैक दिखता है.
INP वैल्यू को फिर से रीसेट करने के लिए, पेज को रीफ़्रेश करें. इसके बाद, हैमबर्गर मेन्यू खोलें. इसे खोलने में कोई समस्या आ रही है.
यह कैसा दिखता है?
{
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
सिलेक्टर को अपने आइडेंटिफ़ायर से बदला जा सकता है. यह बदलाव, टारगेट के कॉम्पोनेंट या टारगेट की एआरआई भूमिकाओं के आधार पर किया जा सकता है.
इसी तरह, scripts
एंट्री के sourceURL
पाथ में फ़ाइल-आधारित हैश हो सकते हैं, जिससे उन्हें जोड़ना मुश्किल हो जाता है. हालांकि, डेटा को वापस भेजने से पहले, अपनी जानी-पहचानी बिल्ड प्रोसेस के आधार पर हैश हटाए जा सकते हैं.
माफ़ करें, इस तरह के जटिल डेटा को डीबग करना आसान नहीं है. हालांकि, डीबग करने की प्रोसेस के लिए, इसके किसी सबसेट का इस्तेमाल करना, बिना किसी एट्रिब्यूशन डेटा का इस्तेमाल करने से ज़्यादा अहम है.
हर जगह क्रेडिट दें!
LoAF पर आधारित 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);