फ़ील्ड में धीमे इंटरैक्शन का पता लगाना

अपनी वेबसाइट के फ़ील्ड डेटा में, धीमे इंटरैक्शन ढूंढने का तरीका जानें, ताकि आप इंटरैक्शन टू नेक्स्ट पेंट को बेहतर बनाने के अवसर ढूंढ सकें.

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

इस गाइड में, आपको Chrome उपयोगकर्ता अनुभव रिपोर्ट (CrUX) के फ़ील्ड डेटा का इस्तेमाल करके, अपनी वेबसाइट के आईएनपी का तुरंत आकलन करने का तरीका पता चलेगा. इससे यह पता चलेगा कि आपकी वेबसाइट में आईएनपी से जुड़ी समस्याएं हैं या नहीं. इसके बाद, आपको वेब-विटल्स JavaScript लाइब्रेरी के एट्रिब्यूशन बिल्ड का इस्तेमाल करने का तरीका पता चलेगा. साथ ही, Long Animation Frames API (LoAF) से मिलने वाली नई अहम जानकारी के बारे में भी पता चलेगा. इस जानकारी का इस्तेमाल करके, अपनी वेबसाइट पर धीमे इंटरैक्शन के लिए फ़ील्ड डेटा इकट्ठा किया जा सकता है और उसका विश्लेषण किया जा सकता है.

अपनी वेबसाइट के INP का आकलन करने के लिए, CrUX से शुरुआत करें

अगर आपकी वेबसाइट के उपयोगकर्ताओं से फ़ील्ड डेटा इकट्ठा नहीं किया जा रहा है, तो CrUX से शुरुआत करना एक अच्छा विकल्प हो सकता है. CrUX, Chrome के उन असली उपयोगकर्ताओं से फ़ील्ड डेटा इकट्ठा करता है जिन्होंने टेलीमेट्री डेटा भेजने के लिए ऑप्ट-इन किया है.

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

  • PageSpeed Insights का इस्तेमाल करके, अलग-अलग पेजों और पूरी ऑरिजिन की जांच की जा सकती है.
  • पेजों के टाइप. उदाहरण के लिए, कई ई-कॉमर्स वेबसाइटों पर प्रॉडक्ट की ज़्यादा जानकारी वाला पेज और प्रॉडक्ट लिस्टिंग पेज टाइप होते हैं. Search Console में, यूनीक पेज टाइप के लिए CrUX डेटा देखा जा सकता है.

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

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

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

web-vitals JavaScript लाइब्रेरी की मदद से फ़ील्ड डेटा इकट्ठा करना

web-vitals JavaScript लाइब्रेरी एक स्क्रिप्ट है. इसे अपनी वेबसाइट पर लोड करके, वेबसाइट के उपयोगकर्ताओं से फ़ील्ड डेटा इकट्ठा किया जा सकता है. इसका इस्तेमाल कई मेट्रिक रिकॉर्ड करने के लिए किया जा सकता है. इनमें, INP भी शामिल है. हालांकि, इसके लिए ज़रूरी है कि आपके ब्राउज़र में INP की सुविधा काम करती हो.

ब्राउज़र के इस्तेमाल से जुड़ी सहायता

  • Chrome: 96.
  • Edge: 96.
  • Firefox: यह सुविधा काम नहीं करती.
  • Safari: यह सुविधा काम नहीं करती.

सोर्स

फ़ील्ड में उपयोगकर्ताओं से बुनियादी INP डेटा पाने के लिए, web-vitals लाइब्रेरी के स्टैंडर्ड बिल्ड का इस्तेमाल किया जा सकता है:

import {onINP} from 'web-vitals';

onINP(({name, value, rating}) => {
  console.log(name);    // 'INP'
  console.log(value);   // 512
  console.log(rating);  // 'poor'
});

उपयोगकर्ताओं से मिले फ़ील्ड डेटा का विश्लेषण करने के लिए, आपको यह डेटा किसी जगह भेजना होगा:

import {onINP} from 'web-vitals';

onINP(({name, value, rating}) => {
  // Prepare JSON to be sent for collection. Note that
  // you can add anything else you'd want to collect here:
  const body = JSON.stringify({name, value, rating});

  // Use `sendBeacon` to send data to an analytics endpoint.
  // For Google Analytics, see https://github.com/GoogleChrome/web-vitals#send-the-results-to-google-analytics.
  navigator.sendBeacon('/analytics', body);
});

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

वेब-विटल्स लाइब्रेरी के एट्रिब्यूशन बिल्ड के साथ आगे बढ़ें

वेब-विटल्स लाइब्रेरी का एट्रिब्यूशन बिल्ड, ज़्यादा डेटा दिखाता है. यह डेटा, फ़ील्ड में मौजूद उपयोगकर्ताओं से मिल सकता है. इससे, आपको अपनी वेबसाइट के आईएनपी पर असर डालने वाले समस्या वाले इंटरैक्शन को बेहतर तरीके से हल करने में मदद मिलती है. इस डेटा को लाइब्रेरी के onINP() तरीके में दिखाए गए attribution ऑब्जेक्ट से ऐक्सेस किया जा सकता है:

import {onINP} from 'web-vitals/attribution';

onINP(({name, value, rating, attribution}) => {
  console.log(name);         // 'INP'
  console.log(value);        // 56
  console.log(rating);       // 'good'
  console.log(attribution);  // Attribution data object
});
वेब-विटल्स लाइब्रेरी के कंसोल लॉग कैसे दिखते हैं. इस उदाहरण में कंसोल, मेट्रिक (INP) का नाम और INP वैल्यू (56) दिखाता है. यह वैल्यू, INP थ्रेशोल्ड (अच्छा) के अंदर है. साथ ही, कंसोल में एट्रिब्यूशन ऑब्जेक्ट में दिखाई गई अलग-अलग जानकारी भी दिखती है. इसमें, The Long Animation Frames API की एंट्री भी शामिल हैं.
वेब-से जुड़ी अहम जानकारी वाली लाइब्रेरी का डेटा, Console में कैसे दिखता है.

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

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

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

attribution ऑब्जेक्ट की कुंजी Data
interactionTarget पेज की INP वैल्यू देने वाले एलिमेंट पर ले जाने वाला सीएसएस सिलेक्टर. उदाहरण के लिए, button#save.
interactionType इंटरैक्शन का टाइप, जो क्लिक, टैप या कीबोर्ड इनपुट से होता है.
inputDelay* इंटरैक्शन का इनपुट में लगा समय.
processingDuration* उपयोगकर्ता के इंटरैक्शन के जवाब में, पहला इवेंट लिसनर कब शुरू हुआ और सभी इवेंट लिसनर की प्रोसेसिंग कब पूरी हुई, उस बीच का समय.
presentationDelay* इंटरैक्शन का प्रज़ेंटेशन में लगने वाला समय. यह समय, इवेंट हैंडलर के खत्म होने से लेकर अगला फ़्रेम पेंट होने तक लगता है.
longAnimationFrameEntries* इंटरैक्शन से जुड़े LoAF की एंट्री. ज़्यादा जानकारी के लिए, अगला लेख पढ़ें.
*चौथे वर्शन में नई सुविधाएं

वेब-विटल्स लाइब्रेरी के वर्शन 4 से, आपको समस्या वाले इंटरैक्शन के बारे में ज़्यादा जानकारी मिल सकती है. इसके लिए, INP फ़ेज़ ब्रेकडाउन (इनपुट में लगा समय, प्रोसेसिंग में लगा समय, और प्रज़ेंटेशन में लगा समय) और लॉन्ग ऐनिमेशन फ़्रेम एपीआई (LoAF) से मिलने वाले डेटा का इस्तेमाल किया जाता है.

Long Animation Frames API (LoAF)

ब्राउज़र के इस्तेमाल से जुड़ी सहायता

  • Chrome: 123.
  • Edge: 123.
  • Firefox: यह सुविधा काम नहीं करती.
  • Safari: यह सुविधा काम नहीं करती.

सोर्स

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

वेब-विटल्स लाइब्रेरी का एट्रिब्यूशन बिल्ड, attribution ऑब्जेक्ट की longAnimationFrameEntries कुंजी के तहत LoAF एंट्री का ऐरे दिखाता है. नीचे दी गई टेबल में, LoAF की हर एंट्री में मौजूद कुछ अहम डेटा की जानकारी दी गई है:

LoAF एंट्री ऑब्जेक्ट की कुंजी Data
duration लंबे ऐनिमेशन फ़्रेम की अवधि, लेआउट के पूरा होने तक. इसमें पेंटिंग और कंपोजिंग शामिल नहीं है.
blockingDuration फ़्रेम में कुल वह समय जो लंबे टास्क की वजह से, ब्राउज़र तुरंत जवाब नहीं दे पाया. ब्लॉकिंग के इस समय में, JavaScript चलाने वाले लंबे टास्क के साथ-साथ फ़्रेम में बाद में होने वाले लंबे रेंडरिंग टास्क भी शामिल हो सकते हैं.
firstUIEventTimestamp फ़्रेम के दौरान, इवेंट को सूची में जोड़े जाने का टाइमस्टैंप. किसी इंटरैक्शन के इनपुट में लगा समय शुरू होने का पता लगाने के लिए, यह मेट्रिक काम की होती है.
startTime फ़्रेम के शुरू होने का टाइमस्टैंप.
renderStart फ़्रेम के लिए रेंडरिंग की प्रोसेस कब शुरू हुई. इसमें कोई भी requestAnimationFrame कॉलबैक (और लागू होने पर ResizeObserver कॉलबैक) शामिल है. हालांकि, यह स्टाइल/लेआउट से जुड़ा काम शुरू होने से पहले हो सकता है.
styleAndLayoutStart जब फ़्रेम में स्टाइल/लेआउट में बदलाव होता है. अन्य उपलब्ध टाइमस्टैंप का इस्तेमाल करते समय, स्टाइल/लेआउट के काम की अवधि का पता लगाने में मददगार हो सकता है.
scripts आइटम का एक कलेक्शन, जिसमें पेज के INP में योगदान देने वाली स्क्रिप्ट एट्रिब्यूशन की जानकारी शामिल होती है.
LoAF मॉडल के हिसाब से, लंबे ऐनिमेशन फ़्रेम का विज़ुअलाइज़ेशन.
LoAF API (minus blockingDuration) के हिसाब से, लंबे ऐनिमेशन फ़्रेम के टाइमिंग का डायग्राम.

इस जानकारी से आपको यह पता चल सकता है कि इंटरैक्शन धीमा क्यों हो रहा है. हालांकि, LoAF एंट्री में दिखने वाले scripts कलेक्शन पर खास ध्यान देना चाहिए:

स्क्रिप्ट एट्रिब्यूशन ऑब्जेक्ट की कुंजी Data
invoker इंवोक करने वाला. यह अगली लाइन में बताए गए, ट्रिगर करने वाले टूल के टाइप के हिसाब से अलग-अलग हो सकता है. इनवोकर्स के उदाहरण के तौर पर, 'IMG#id.onload', 'Window.requestAnimationFrame' या 'Response.json.then' जैसी वैल्यू दी जा सकती हैं.
invokerType इंवोक करने वाले का टाइप. यह 'user-callback', 'event-listener', 'resolve-promise', 'reject-promise', 'classic-script' या 'module-script' हो सकता है.
sourceURL उस स्क्रिप्ट का यूआरएल जहां से लंबा ऐनिमेशन फ़्रेम शुरू हुआ.
sourceCharPosition स्क्रिप्ट में कैरेक्टर की वह जगह जिसकी पहचान sourceURL से की गई है.
sourceFunctionName पहचानी गई स्क्रिप्ट में मौजूद फ़ंक्शन का नाम.

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

इंटरैक्शन के धीमे होने की सामान्य वजहों की पहचान करना और उन्हें मेज़र करना

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

प्रोसेस होने में ज़्यादा समय लगना

किसी इंटरैक्शन को प्रोसेस होने में लगने वाला समय, वह समय होता है जो इंटरैक्शन के रजिस्टर किए गए इवेंट हैंडलर कॉलबैक को पूरा होने में लगता है. साथ ही, इसमें इंटरैक्शन के दौरान होने वाली अन्य सभी गतिविधियां भी शामिल होती हैं. वेब-विटल्स लाइब्रेरी, प्रोसेसिंग में लगने वाले लंबे समय की जानकारी दिखाती है:

import {onINP} from 'web-vitals/attribution';

onINP(({name, value, attribution}) => {
  const {processingDuration} = attribution; // 512.5
});

यह सोचना स्वाभाविक है कि इंटरैक्शन में लगने वाले समय की मुख्य वजह यह है कि आपके इवेंट हैंडलर कोड को चलने में बहुत ज़्यादा समय लगा. हालांकि, ऐसा हमेशा नहीं होता! इस बात की पुष्टि करने के बाद कि समस्या यही है, LoAF डेटा की मदद से ज़्यादा जानकारी हासिल की जा सकती है:

import {onINP} from 'web-vitals/attribution';

onINP(({name, value, attribution}) => {
  const {processingDuration} = attribution; // 512.5

  // Get the longest script from LoAF covering `processingDuration`:
  const loaf = attribution.longAnimationFrameEntries.at(-1);
  const script = loaf?.scripts.sort((a, b) => b.duration - a.duration)[0];

  if (script) {
    // Get attribution for the long-running event handler:
    const {invokerType} = script;        // 'event-listener'
    const {invoker} = script;            // 'BUTTON#update.onclick'
    const {sourceURL} = script;          // 'https://example.com/app.js'
    const {sourceCharPosition} = script; // 83
    const {sourceFunctionName} = script; // 'update'
  }
});

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

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

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

इनपुट में ज़्यादा देरी

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

import {onINP} from 'web-vitals/attribution';

onINP(({name, value, attribution}) => {
  const {inputDelay} = attribution; // 125.59439536
});

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

क्या यह पेज लोड होने के दौरान हुआ था?

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

import {onINP} from 'web-vitals/attribution';

onINP(({name, value, attribution}) => {
  const {inputDelay} = attribution; // 125.59439536

  // Get the longest script from the first LoAF entry:
  const loaf = attribution.longAnimationFrameEntries[0];
  const script = loaf?.scripts.sort((a, b) => b.duration - a.duration)[0];

  if (script) {
    // Invoker types can describe if script eval blocked the main thread:
    const {invokerType} = script;    // 'classic-script' | 'module-script'
    const {sourceLocation} = script; // 'https://example.com/app.js'
  }
});

अगर इस डेटा को फ़ील्ड में रिकॉर्ड करने पर, आपको ज़्यादा इंपुट देरी और 'classic-script' या 'module-script' टाइप के इनवोकर्स दिखते हैं, तो यह माना जा सकता है कि आपकी साइट पर मौजूद स्क्रिप्ट का आकलन करने में काफ़ी समय लग रहा है. साथ ही, इंटरैक्शन में देरी करने के लिए, मुख्य थ्रेड को काफ़ी देर तक ब्लॉक किया जा रहा है. अपनी स्क्रिप्ट को छोटे बंडल में बांटकर, शुरुआत में इस्तेमाल नहीं किए गए कोड को बाद में लोड करने के लिए रोककर, और अपनी साइट का ऑडिट करके, इस्तेमाल नहीं किए गए कोड को पूरी तरह से हटाया जा सकता है. इससे, ब्लॉक होने का समय कम हो जाता है.

क्या यह पेज लोड होने के बाद हुआ?

आम तौर पर, इनपुट में देरी तब होती है, जब पेज लोड हो रहा हो. हालांकि, यह भी हो सकता है कि पेज लोड होने के बाद भी इनपुट में देरी हो. ऐसा किसी दूसरी वजह से हो सकता है. पेज लोड होने के बाद इनपुट में देरी होने की सामान्य वजहें, पहले किए गए setInterval कॉल की वजह से समय-समय पर चलने वाला कोड या ऐसे इवेंट कॉलबैक हो सकते हैं जिन्हें पहले चलाने के लिए कतार में लगाया गया था और वे अब भी प्रोसेस में हैं.

import {onINP} from 'web-vitals/attribution';

onINP(({name, value, attribution}) => {
  const {inputDelay} = attribution; // 125.59439536

  // Get the longest script from the first LoAF entry:
  const loaf = attribution.longAnimationFrameEntries[0];
  const script = loaf?.scripts.sort((a, b) => b.duration - a.duration)[0];

  if (script) {
    const {invokerType} = script;        // 'user-callback'
    const {sourceURL} = script;          // 'https://example.com/app.js'
    const {sourceCharPosition} = script; // 83
    const {sourceFunctionName} = script; // 'update'
  }
});

प्रोसेसिंग में लगने वाले समय की ज़्यादा वैल्यू की समस्या हल करने की तरह ही, ऊपर बताई गई वजहों से इनपुट में होने वाली ज़्यादा देरी की वजह से, आपको स्क्रिप्ट एट्रिब्यूशन का ज़्यादा जानकारी वाला डेटा मिलेगा. हालांकि, इसमें अंतर यह है कि इंटरैक्शन में देरी करने वाले काम की प्रकृति के आधार पर, ट्रिगर करने वाले टूल का टाइप बदल जाएगा:

  • 'user-callback' से पता चलता है कि ब्लॉक करने का टास्क setInterval, setTimeout या requestAnimationFrame से मिला था.
  • 'event-listener' से पता चलता है कि ब्लॉक करने का टास्क, पहले के किसी इनपुट से था, जिसे सूची में जोड़ दिया गया था और अब भी प्रोसेस किया जा रहा है.
  • 'resolve-promise' और 'reject-promise' का मतलब है कि ब्लॉक करने वाला टास्क, किसी ऐसे काम से जुड़ा था जिसे पहले शुरू किया गया था और जिसे तब हल या अस्वीकार किया गया था, जब उपयोगकर्ता ने पेज से इंटरैक्ट करने की कोशिश की थी. इससे इंटरैक्शन में देरी हुई.

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

प्रज़ेंटेशन में ज़्यादा देरी

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

import {onINP} from 'web-vitals/attribution';

onINP(({name, value, attribution}) => {
  const {presentationDelay} = attribution; // 113.32307691
});

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

स्टाइल और लेआउट में ज़्यादा काम करना

प्रज़ेंटेशन में देरी होने की कई वजहें हो सकती हैं. जैसे, स्टाइल की फिर से गिनती और लेआउट से जुड़ा काम. ये काम कई वजहों से हो सकते हैं. जैसे, जटिल सीएसएस सेलेक्टर और बड़े DOM साइज़. वेब-विटल्स लाइब्रेरी में दिखने वाले LoAF के समय से, इस काम में लगने वाले समय का पता लगाया जा सकता है:

import {onINP} from 'web-vitals/attribution';

onINP(({name, value, attribution}) => {
  const {presentationDelay} = attribution; // 113.32307691

  // Get the longest script from the last LoAF entry:
  const loaf = attribution.longAnimationFrameEntries.at(-1);
  const script = loaf?.scripts.sort((a, b) => b.duration - a.duration)[0];

  // Get necessary timings:
  const {startTime} = loaf; // 2120.5
  const {duration} = loaf;  // 1002

  // Figure out the ending timestamp of the frame (approximate):
  const endTime = startTime + duration; // 3122.5

  // Get the start timestamp of the frame's style/layout work:
  const {styleAndLayoutStart} = loaf; // 3011.17692309

  // Calculate the total style/layout duration:
  const styleLayoutDuration = endTime - styleAndLayoutStart; // 111.32307691

  if (script) {
    // Get attribution for the event handler that triggered
    // the long-running style and layout operation:
    const {invokerType} = script;        // 'event-listener'
    const {invoker} = script;            // 'BUTTON#update.onclick'
    const {sourceURL} = script;          // 'https://example.com/app.js'
    const {sourceCharPosition} = script; // 83
    const {sourceFunctionName} = script; // 'update'
  }
});

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

लंबे समय तक चलने वाले requestAnimationFrame कॉलबैक

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

अगर इन कॉलबैक में किया जाने वाला काम मुश्किल है, तो इन्हें पूरा होने में काफ़ी समय लग सकता है. अगर आपको लगता है कि प्रज़ेंटेशन में देरी की ज़्यादा वैल्यू, requestAnimationFrame के साथ किए जा रहे काम की वजह से है, तो इन स्थितियों की पहचान करने के लिए, वेब-विटल्स लाइब्रेरी से मिले LoAF डेटा का इस्तेमाल किया जा सकता है:

onINP(({name, value, attribution}) => {
  const {presentationDelay} = attribution; // 543.1999999880791

  // Get the longest script from the last LoAF entry:
  const loaf = attribution.longAnimationFrameEntries.at(-1);
  const script = loaf?.scripts.sort((a, b) => b.duration - a.duration)[0];

  // Get the render start time and when style and layout began:
  const {renderStart} = loaf;         // 2489
  const {styleAndLayoutStart} = loaf; // 2989.5999999940395

  // Calculate the `requestAnimationFrame` callback's duration:
  const rafDuration = styleAndLayoutStart - renderStart; // 500.59999999403954

  if (script) {
    // Get attribution for the event handler that triggered
    // the long-running requestAnimationFrame callback:
    const {invokerType} = script;        // 'user-callback'
    const {invoker} = script;            // 'FrameRequestCallback'
    const {sourceURL} = script;          // 'https://example.com/app.js'
    const {sourceCharPosition} = script; // 83
    const {sourceFunctionName} = script; // 'update'
  }
});

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

नतीजा

फ़ील्ड डेटा, जानकारी का सबसे अच्छा सोर्स है. इससे यह समझने में मदद मिलती है कि फ़ील्ड में मौजूद असल उपयोगकर्ताओं के लिए कौनसे इंटरैक्शन समस्या पैदा करते हैं. फ़ील्ड डेटा इकट्ठा करने वाले टूल, जैसे कि वेब-विटल्स JavaScript लाइब्रेरी (या RUM की सेवा देने वाली कंपनी) का इस्तेमाल करके, यह पता लगाया जा सकता है कि किन इंटरैक्शन में सबसे ज़्यादा समस्याएं आ रही हैं. इसके बाद, लैब में समस्या वाले इंटरैक्शन को फिर से चलाकर, उन्हें ठीक किया जा सकता है.

Unsplash से ली गई हीरो इमेज, जिसे फ़ेडरिको रेस्पिनी ने बनाया है.