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

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

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

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

अपनी वेबसाइट के आईएनपी का आकलन करने के लिए, CrUX का इस्तेमाल करें

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

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

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

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

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

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

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

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

Browser Support

  • Chrome: 96.
  • Edge: 96.
  • Firefox: 144.
  • Safari: not supported.

Source

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

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 के मुकाबले ज़्यादा जानकारी नहीं मिलती. ऐसे में, web-vitals लाइब्रेरी का एट्रिब्यूशन बिल्ड काम आता है.

वेब-वाइटल्स लाइब्रेरी के एट्रिब्यूशन बिल्ड का इस्तेमाल करके, ज़्यादा जानकारी पाएं

वेब-वाइटल्स लाइब्रेरी का एट्रिब्यूशन बिल्ड, फ़ील्ड में मौजूद उपयोगकर्ताओं से अतिरिक्त डेटा इकट्ठा करता है. इससे आपको उन समस्याओं को बेहतर तरीके से हल करने में मदद मिलती है जो आपकी वेबसाइट के आईएनपी पर असर डाल रही हैं. इस डेटा को, लाइब्रेरी के 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
});
वेब-वाइटल्स लाइब्रेरी से कंसोल लॉग कैसे दिखते हैं. इस उदाहरण में कंसोल, मेट्रिक का नाम (आईएनपी), आईएनपी वैल्यू (56), और आईएनपी थ्रेशोल्ड (अच्छा) के हिसाब से उस वैल्यू की जगह दिखाता है. साथ ही, एट्रिब्यूशन ऑब्जेक्ट में दिखाई गई अलग-अलग जानकारी दिखाता है. इसमें Long Animation Frames API की एंट्री भी शामिल हैं.
वेब-वाइटल्स लाइब्रेरी का डेटा, कंसोल में कैसे दिखता है.

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

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

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

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

web-vitals लाइब्रेरी के वर्शन 4 से, आपको समस्या वाले इंटरैक्शन के बारे में ज़्यादा जानकारी मिल सकती है. इसके लिए, यह लाइब्रेरी INP के फ़ेज़ के ब्रेकडाउन (इनपुट में देरी, प्रोसेसिंग में लगने वाला समय, और प्रज़ेंटेशन में देरी) और Long Animation Frames API (LoAF) के साथ डेटा उपलब्ध कराती है.

Long Animation Frames API (LoAF)

Browser Support

  • Chrome: 123.
  • Edge: 123.
  • Firefox: not supported.
  • Safari: not supported.

Source

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

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

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

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

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

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

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

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.toSorted((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.toSorted((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' का मतलब है कि ब्लॉक करने वाला टास्क, किसी ऐसे एसिंक्रोनस काम से था जिसे पहले शुरू किया गया था. साथ ही, जब उपयोगकर्ता ने पेज से इंटरैक्ट करने की कोशिश की, तब उसे हल कर दिया गया या अस्वीकार कर दिया गया. इससे इंटरैक्शन में देरी हुई.

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

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

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

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

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

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

स्टाइल और लेआउट पर ज़्यादा खर्च करना

प्रजेंटेशन में ज़्यादा समय लगने की वजह से, स्टाइल की फिर से गणना और लेआउट से जुड़े काम में ज़्यादा समय लग सकता है. इसकी कई वजहें हो सकती हैं. जैसे, जटिल सीएसएस सेलेक्टर और बड़े DOM साइज़. वेब-vitals लाइब्रेरी में 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.toSorted((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 के साथ काम करने की वजह से, प्रज़ेंटेशन में ज़्यादा देरी हो रही है, तो इन स्थितियों का पता लगाने के लिए, web-vitals लाइब्रेरी से मिले 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.toSorted((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 से ली गई हीरो इमेज. इसे Federico Respini ने बनाया है.