ফিল্ডে স্লো ইন্টার‍্যাকশন খুঁজুন

আপনার ওয়েবসাইটের ফিল্ড ডেটাতে কীভাবে স্লো ইন্টার‍্যাকশন খুঁজে পাবেন তা জানুন যাতে আপনি এর Interaction to Next Paint উন্নত করার সুযোগ খুঁজে পেতে পারেন।

ফিল্ড ডেটা হল এমন ডেটা যা আপনাকে জানায় যে আসল ব্যবহারকারীরা আপনার ওয়েবসাইট কীভাবে ব্যবহার করছেন। এটি এমন সমস্যা খুঁজে বের করে যা আপনি শুধু ল্যাব ডেটা থেকে খুঁজে পাবেন না। ইন্টার‍্যাকশন টু নেক্সট পেইন্ট (INP)-এর ক্ষেত্রে, ধীর ইন্টার‍্যাকশন শনাক্ত করার জন্য ফিল্ড ডেটা অপরিহার্য এবং সেগুলি ঠিক করতে আপনাকে সাহায্য করার জন্য গুরুত্বপূর্ণ সূত্র প্রদান করে।

এই গাইডে, আপনি শিখবেন কীভাবে Chrome User Experience Report (CrUX) থেকে ফিল্ড ডেটা ব্যবহার করে আপনার ওয়েবসাইটের INP দ্রুত মূল্যায়ন করবেন যাতে আপনার ওয়েবসাইটে INP-এর সমস্যা আছে কিনা তা দেখতে পারেন। এরপরে, আপনি web-vitals JavaScript লাইব্রেরির অ্যাট্রিবিউশন বিল্ড কীভাবে ব্যবহার করতে হয় তা শিখবেন—এবং এটি লং অ্যানিমেশন ফ্রেম API (LoAF) থেকে যে নতুন ইনসাইট প্রদান করে—আপনার ওয়েবসাইটে স্লো ইন্টার‍্যাকশনের জন্য ফিল্ড ডেটা সংগ্রহ ও ব্যাখ্যা করতে।

আপনার ওয়েবসাইটের INP মূল্যায়ন করতে CrUX ব্যবহার করা শুরু করুন

আপনি যদি নিজের ওয়েবসাইটের ব্যবহারকারীদের থেকে ফিল্ড ডেটা সংগ্রহ না করেন, তাহলে CrUX একটি ভালো শুরুর পয়েন্ট হতে পারে। CrUX সেইসব আসল Chrome ব্যবহারকারীদের থেকে ফিল্ড ডেটা সংগ্রহ করে যারা টেলিমেট্রি ডেটা পাঠানোর বিকল্প বেছে নিয়েছেন।

CrUX ডেটা বিভিন্ন জায়গায় দেখানো হয় এবং আপনি যে তথ্য খুঁজছেন তার পরিধির উপর এটি নির্ভর করে। CrUX, INP এবং অন্যান্য Core Web Vitals-এর জন্য ডেটা প্রদান করতে পারে:

  • PageSpeed Insights ব্যবহার করে স্বতন্ত্র পৃষ্ঠা এবং সম্পূর্ণ অরিজিন।
  • পৃষ্ঠার ধরন। যেমন, অনেক ই-কমার্স ওয়েবসাইটে প্রোডাক্ট বিবরণ পৃষ্ঠা এবং প্রোডাক্ট তালিকা পৃষ্ঠা থাকে। আপনি Search Console-এ অনন্য পৃষ্ঠার ধরনের জন্য CrUX ডেটা পেতে পারেন।

শুরু করার জন্য, আপনি PageSpeed Insights-এ আপনার ওয়েবসাইটের URL লিখতে পারেন। আপনি URL লিখলে, সেটির ফিল্ড ডেটা—যদি উপলভ্য থাকে—INP সহ একাধিক মেট্রিকের জন্য দেখানো হবে। এছাড়াও, আপনি টগল ব্যবহার করে মোবাইল ও ডেস্কটপ ডাইমেনশনের জন্য INP ভ্যালু চেক করতে পারবেন।

PageSpeed Insights-এ CrUX-এর দেখানো ফিল্ড ডেটা, তিনটি Core Web Vitals-এ LCP, INP, CLS এবং ডায়াগনস্টিক মেট্রিক হিসেবে TTFB, FCP এবং বন্ধ হয়ে যাওয়া Core Web Vital মেট্রিক হিসেবে FID দেখাচ্ছে।
PageSpeed insights-এ যেমন দেখা যায়, CrUX ডেটার রিডআউট। এই উদাহরণে, প্রদত্ত ওয়েব পৃষ্ঠার INP উন্নত করতে হবে।

এই ডেটা গুরুত্বপূর্ণ কারণ এটি আপনাকে জানায় যে আপনার কোনও সমস্যা আছে কিনা। তবে, CrUX যা করতে পারে না তা হল, কী কারণে সমস্যা হচ্ছে তা আপনাকে জানানো। অনেক রিয়েল ইউজার মনিটরিং (RUM) সমাধান উপলভ্য আছে যা আপনাকে ওয়েবসাইটের ব্যবহারকারীদের থেকে ফিল্ড ডেটা সংগ্রহ করতে সাহায্য করবে। এর ফলে আপনি প্রশ্নের উত্তর দিতে পারবেন। একটি বিকল্প হল, web-vitals JavaScript লাইব্রেরি ব্যবহার করে নিজেই ফিল্ড ডেটা সংগ্রহ করা।

web-vitals জাভাস্ক্রিপ্ট লাইব্রেরির মাধ্যমে ফিল্ড ডেটা সংগ্রহ করা

web-vitals জাভাস্ক্রিপ্ট লাইব্রেরি হল একটি স্ক্রিপ্ট যা আপনি নিজের ওয়েবসাইটে লোড করতে পারেন যাতে আপনার ওয়েবসাইটের ব্যবহারকারীদের থেকে ফিল্ড ডেটা সংগ্রহ করা যায়। আপনি এটি ব্যবহার করে ব্রাউজারে INP সহ একাধিক মেট্রিক রেকর্ড করতে পারবেন।

Browser Support

  • Chrome: 96.
  • Edge: 96.
  • Firefox: 144.
  • Safari: 26.2.

Source

ব্যবহারকারীদের থেকে ফিল্ডে প্রাথমিক 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-এর থেকে বেশি কিছু জানা যায় না। এখানেই web-vitals লাইব্রেরির অ্যাট্রিবিউশন বিল্ডের ভূমিকা আসে।

web-vitals লাইব্রেরির অ্যাট্রিবিউশন বিল্ডের মাধ্যমে আরও বেশি সুবিধা পান

ওয়েব-ভাইটাল লাইব্রেরির অ্যাট্রিবিউশন বিল্ড অতিরিক্ত ডেটা দেখায় যা আপনি ফিল্ডে ব্যবহারকারীদের থেকে পেতে পারেন। এটি আপনার ওয়েবসাইটের INP-কে প্রভাবিত করছে এমন সমস্যাযুক্ত ইন্টার‍্যাকশন আরও ভালোভাবে সমাধান করতে সাহায্য করে। এই ডেটা লাইব্রেরির 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
});
web-vitals লাইব্রেরি থেকে কনসোল লগ কীভাবে দেখা যায়। এই উদাহরণের কনসোল মেট্রিকের নাম (INP), INP ভ্যালু (৫৬), INP থ্রেশহোল্ডের মধ্যে সেই ভ্যালু কোথায় আছে (ভাল) এবং অ্যাট্রিবিউশন অবজেক্টে দেখানো তথ্যের বিভিন্ন বিট দেখায়, যার মধ্যে Long Animation Frames API থেকে এন্ট্রিও অন্তর্ভুক্ত।
কনসোলে web-vitals লাইব্রেরি থেকে ডেটা কীভাবে দেখা যায়।

পেজের INP ছাড়াও, অ্যাট্রিবিউশন বিল্ড অনেক ডেটা প্রদান করে যা আপনি স্লো ইন্টার‍্যাকশনের কারণ বুঝতে ব্যবহার করতে পারেন, যার মধ্যে ইন্টার‍্যাকশনের কোন অংশে আপনার ফোকাস করা উচিত তা অন্তর্ভুক্ত রয়েছে। এটি আপনাকে গুরুত্বপূর্ণ প্রশ্নের উত্তর দিতে সাহায্য করতে পারে, যেমন:

  • "পৃষ্ঠা লোড হওয়ার সময় ব্যবহারকারী কি পৃষ্ঠার সাথে ইন্টার‍্যাক্ট করেছেন?"
  • "ইন্টার‍্যাকশনের ইভেন্ট হ্যান্ডলার কি অনেকক্ষণ ধরে চলেছে?"
  • "ইন্টার‍্যাকশন ইভেন্ট হ্যান্ডলার কোড শুরু হতে কি দেরি হয়েছে? যদি তাই হয়, তাহলে সেই সময় মূল থ্রেডে আর কী কী হচ্ছিল?"
  • "ইন্টার‍্যাকশনের ফলে কি অনেক বেশি রেন্ডারিংয়ের কাজ হয়েছে যার ফলে পরবর্তী ফ্রেম পেইন্ট হতে দেরি হয়েছে?"

নিচের সারণীতে কিছু প্রাথমিক অ্যাট্রিবিউশন ডেটা দেখানো হয়েছে যা আপনি লাইব্রেরি থেকে পেতে পারেন। এটি আপনার ওয়েবসাইটে স্লো ইন্টার‍্যাকশনের কিছু উচ্চ-স্তরের কারণ খুঁজে বের করতে সাহায্য করতে পারে:

attribution অবজেক্ট 'কী' ডেটা
interactionTarget CSS সিলেক্টর সেই এলিমেন্টকে পয়েন্ট করে যেটি পৃষ্ঠার INP ভ্যালু তৈরি করেছে—যেমন, button#save।
interactionType ইন্টার‍্যাকশনের ধরন, ক্লিক, ট্যাপ বা কীবোর্ড ইনপুট থেকে।
inputDelay* ইন্ট্যার‍্যাকশনের ইনপুট সংক্রান্ত দেরি।
processingDuration* ব্যবহারকারীর ইন্টার‍্যাকশনের উত্তরে প্রথম ইভেন্ট লিসেনার চলা শুরু হওয়া থেকে সব ইভেন্ট লিসেনার প্রসেসিং শেষ হওয়া পর্যন্ত সময়।
presentationDelay* ইন্টার‍্যাকশনের প্রেজেন্টেশন ডিলে, যা ইভেন্ট হ্যান্ডলার শেষ হওয়ার সময় থেকে শুরু করে পরবর্তী ফ্রেম আঁকা পর্যন্ত সময় নেয়।
longAnimationFrameEntries* ইন্টার‍্যাকশনের সাথে যুক্ত LoAF থেকে এন্ট্রি। অতিরিক্ত তথ্যের জন্য পরেরটি দেখুন।
*ভার্সন ৪-এ নতুন

web-vitals লাইব্রেরির ভার্সন ৪ থেকে শুরু করে, আপনি INP ফেজ ব্রেকডাউন (ইনপুট বিলম্ব, প্রসেসিংয়ের সময়সীমা এবং প্রেজেন্টেশন বিলম্ব) এবং লং অ্যানিমেশন ফ্রেম API (LoAF)-এর মাধ্যমে প্রদান করা ডেটার সাহায্যে সমস্যাযুক্ত ইন্টার‍্যাকশন সম্পর্কে আরও গভীর ইনসাইট পেতে পারেন।

লং অ্যানিমেশন ফ্রেম API (LoAF)

Browser Support

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

Source

ফিল্ড ডেটা ব্যবহার করে ইন্টার‍্যাকশন ডিবাগ করা একটি চ্যালেঞ্জিং কাজ। তবে, LoAF থেকে পাওয়া ডেটার সাহায্যে, এখন স্লো ইন্টার‍্যাকশনের পিছনে থাকা কারণ সম্পর্কে আরও ভাল ইনসাইট পাওয়া সম্ভব, কারণ LoAF বেশ কিছু বিস্তারিত টাইমিং এবং অন্যান্য ডেটা প্রকাশ করে যা আপনি সঠিক কারণ চিহ্নিত করতে ব্যবহার করতে পারেন—এবং আরও গুরুত্বপূর্ণভাবে, আপনার ওয়েবসাইটের কোডে সমস্যার সোর্স কোথায় তা জানতে পারেন।

web-vitals লাইব্রেরির অ্যাট্রিবিউশন বিল্ড attribution অবজেক্টের longAnimationFrameEntries কী-এর অধীনে LoAF এন্ট্রির একটি অ্যারে প্রকাশ করে। নিম্নলিখিত সারণীতে কিছু গুরুত্বপূর্ণ ডেটা তালিকাভুক্ত করা হয়েছে যা আপনি প্রতিটি LoAF এন্ট্রিতে দেখতে পাবেন:

LoAF এন্ট্রি অবজেক্ট কী ডেটা
duration লং অ্যানিমেশন ফ্রেমের সময়সীমা, লেআউট শেষ হওয়া পর্যন্ত, তবে পেইন্টিং ও কম্পোজিটিং বাদ দিয়ে।
blockingDuration ফ্রেমের মোট সময়, যে সময়ে বড় টাস্কের কারণে ব্রাউজার দ্রুত উত্তর দিতে পারেনি। এই ব্লকিং টাইমে জাভাস্ক্রিপ্ট রান করা বড় টাস্কের পাশাপাশি ফ্রেমে পরবর্তী যেকোনও বড় রেন্ডারিং টাস্ক অন্তর্ভুক্ত থাকতে পারে।
firstUIEventTimestamp ফ্রেম চলাকালীন ইভেন্টটি কখন সারিবদ্ধ করা হয়েছিল তার টাইমস্ট্যাম্প। ইন্ট্যার‌্যাকশনের ইনপুট ডিলে কখন শুরু হচ্ছে তা বুঝতে সাহায্য করে।
startTime ফ্রেমের শুরুর টাইমস্ট্যাম্প।
renderStart ফ্রেমের জন্য রেন্ডারিংয়ের কাজ কখন শুরু হয়েছে। এর মধ্যে যেকোনও requestAnimationFrame কলব্যাক (এবং প্রযোজ্য হলে ResizeObserver কলব্যাক) অন্তর্ভুক্ত, তবে সম্ভাব্যভাবে যেকোনও স্টাইল/লেআউট কাজ শুরু হওয়ার আগে।
styleAndLayoutStart ফ্রেমে স্টাইল/লেআউট সংক্রান্ত কাজ হলে। অন্যান্য উপলভ্য টাইমস্ট্যাম্পে স্টাইল/লেআউট কাজের দৈর্ঘ্য নির্ধারণ করার সময় এটি কার্যকর হতে পারে।
scripts পৃষ্ঠার INP-তে অবদান রাখা স্ক্রিপ্ট অ্যাট্রিবিউশন তথ্য সহ আইটেমের অ্যারে।
LoAF মডেল অনুযায়ী লং অ্যানিমেশন ফ্রেমের ভিজ্যুয়ালাইজেশন।
LoAF API (মাইনাস blockingDuration) অনুযায়ী লং অ্যানিমেশন ফ্রেমের টাইমিংয়ের ডায়াগ্রাম।

এইসব তথ্য থেকে আপনি জানতে পারবেন যে কী কারণে ইন্টার‍্যাকশন স্লো হয়ে যায়—তবে LoAF এন্ট্রির মাধ্যমে যে scripts অ্যারে দেখানো হয়, সেটি বিশেষভাবে গুরুত্বপূর্ণ:

স্ক্রিপ্ট অ্যাট্রিবিউশন অবজেক্ট কী ডেটা
invoker ইনভোকার। পরের সারিতে উল্লেখ করা ইনভোকার টাইপের উপর ভিত্তি করে এটি আলাদা হতে পারে। ইনভোকারের উদাহরণ হিসেবে 'IMG#id.onload', 'Window.requestAnimationFrame' বা 'Response.json.then'-এর মতো ভ্যালু হতে পারে।
invokerType ইনভোকারের ধরন। 'user-callback', 'event-listener', 'resolve-promise', 'reject-promise', 'classic-script' বা 'module-script' হতে পারে।
sourceURL স্ক্রিপ্টের URL যেখানে লং অ্যানিমেশন ফ্রেমের উৎপত্তি হয়েছে।
sourceCharPosition sourceURL দ্বারা শনাক্ত করা স্ক্রিপ্টে অক্ষরের অবস্থান।
sourceFunctionName শনাক্ত করা স্ক্রিপ্টে ফাংশনের নাম।

এই অ্যারের প্রতিটি এন্ট্রিতে এই টেবিলে দেখানো ডেটা থাকে, যা আপনাকে সেই স্ক্রিপ্ট সম্পর্কে তথ্য দেয় যা স্লো ইন্টার‍্যাকশনের জন্য দায়ী ছিল—এবং কীভাবে এটি দায়ী ছিল।

ধীর ইন্ট্যার‌্যাকশনের পিছনে সাধারণ কারণগুলি পরিমাপ ও শনাক্ত করুন

আপনি কীভাবে এই তথ্য ব্যবহার করতে পারেন সেই সম্পর্কে আপনাকে ধারণা দিতে, এই নির্দেশিকা এখন আপনাকে দেখাবে যে কীভাবে আপনি web-vitals লাইব্রেরিতে দেখানো LoAF ডেটা ব্যবহার করে স্লো ইন্টার‍্যাকশনের পিছনে কিছু কারণ নির্ধারণ করতে পারেন।

প্রসেস করার দীর্ঘ সময়সীমা

ইন্টার‍্যাকশনের প্রসেসিংয়ের সময়কাল হল ইন্টার‍্যাকশনের রেজিস্টার করা ইভেন্ট হ্যান্ডলার কলব্যাক সম্পূর্ণ হতে এবং তাদের মধ্যে অন্য কিছু ঘটতে যে সময় লাগে। প্রসেসিংয়ের জন্য বেশি সময় লাগার বিষয়টি web-vitals লাইব্রেরি থেকে জানা যায়:

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
});

আপনি যদি লক্ষ্য করেন যে কিছু ইন্টার‍্যাকশনে ইনপুট ডিলে বেশি হচ্ছে, তাহলে ইন্টার‍্যাকশনের সময় পৃষ্ঠায় কী ঘটছিল তা আপনাকে খুঁজে বের করতে হবে যার কারণে ইনপুট ডিলে বেশি হচ্ছে—এবং এটি প্রায়শই ইন্টার‍্যাকশনটি পৃষ্ঠা লোড হওয়ার সময় বা পরে ঘটেছে কিনা তা নির্ধারণ করে।

এটি কি পৃষ্ঠা লোড হওয়ার সময় হয়েছিল?

কোনও পৃষ্ঠা লোড হওয়ার সময় প্রধান থ্রেড প্রায়শই সবচেয়ে ব্যস্ত থাকে। এই সময়, সব ধরনের টাস্ক সারিবদ্ধভাবে প্রসেস করা হয় এবং এই সব কাজ চলাকালীন ব্যবহারকারী পৃষ্ঠার সাথে ইন্টার‍্যাক্ট করার চেষ্টা করলে, ইন্টার‍্যাকশনে দেরি হতে পারে। যেসব পৃষ্ঠা প্রচুর জাভাস্ক্রিপ্ট লোড করে, সেগুলি স্ক্রিপ্ট কম্পাইল ও মূল্যায়ন করার কাজ শুরু করতে পারে, এর পাশাপাশি ব্যবহারকারীর ইন্টার‍্যাকশনের জন্য পৃষ্ঠা রেডি করার ফাংশনও এক্সিকিউট করতে পারে। এই অ্যাক্টিভিটি চলাকালীন ব্যবহারকারী ইন্টার‍্যাক্ট করলে, এই কাজ বাধা সৃষ্টি করতে পারে এবং আপনার ওয়েবসাইটের ব্যবহারকারীদের ক্ষেত্রে এটি হচ্ছে কিনা তা আপনি খুঁজে দেখতে পারেন:

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
});

আপনি যদি এই ডেটা রেকর্ড করেন এবং আপনার ওয়েবসাইটের INP-তে অবদান রাখা ইন্টার‍্যাকশনের জন্য প্রেজেন্টেশন ডিলে বেশি দেখেন, তাহলে এর জন্য দায়ী কারণগুলি আলাদা হতে পারে, তবে এখানে কয়েকটি কারণ রয়েছে যেগুলি লক্ষ্য রাখতে হবে।

স্টাইল ও লেআউট সংক্রান্ত কাজ করতে অনেক খরচ হয়

প্রেজেন্টেশনে দীর্ঘ বিলম্বের কারণ হতে পারে জটিল CSS সিলেক্টর ও বড় DOM সাইজ সহ বিভিন্ন কারণে হওয়া স্টাইল রিক্যালকুলেশন ও লেআউট সংক্রান্ত কাজ। আপনি web-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-কে স্পর্শ করে না বা স্টাইল আপডেট করে না এমন যেকোনও কাজ পরবর্তী ফ্রেম আঁকার ক্ষেত্রে অপ্রয়োজনীয়ভাবে দেরি করবে, তাই সতর্ক থাকুন!

উপসংহার

ফিল্ডে আসল ব্যবহারকারীদের জন্য কোন ইন্টার‍্যাকশনগুলি সমস্যাজনক তা বোঝার ক্ষেত্রে ফিল্ড ডেটা হল তথ্যের সেরা উৎস। web-vitals জাভাস্ক্রিপ্ট লাইব্রেরি (বা RUM প্রোভাইডার)-এর মতো ফিল্ড ডেটা সংগ্রহের টুলের উপর নির্ভর করে, আপনি আরও আত্মবিশ্বাসের সাথে বুঝতে পারবেন যে কোন ইন্টার‍্যাকশনগুলি সবচেয়ে বেশি সমস্যাজনক এবং তারপর ল্যাবে সমস্যাজনক ইন্টার‍্যাকশনগুলি আবার তৈরি করে সেগুলি সমাধান করার চেষ্টা করতে পারবেন।