খারাপ INP-এর কারণ শনাক্ত করা

ইন্টার‍্যাকশনের ক্ষেত্রে রেসপন্সিভনেস খারাপ হলে, পৃষ্ঠাটি ধীরে কাজ করছে বা সম্পূর্ণভাবে ভেঙে গেছে বলে মনে হতে পারে। Interaction to Next Paint (INP) হল ইভেন্ট টাইমিং API-এর উপর ভিত্তি করে তৈরি একটি মেট্রিক। এটি পৃষ্ঠার রেসপন্সিভনেসের পরিমাপ হিসেবে সবচেয়ে খারাপ ইন্টারঅ্যাকশন (কিছু আউটলায়ার বাদ দিয়ে) পরিমাপ করে।

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

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

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

  • স্ক্রিপ্ট-লেভেল ফোর্সড স্টাইল ও লেআউট (forcedStyleDuration এবং forcedLayoutDuration): ইনপুট ডিলে বা প্রসেসিংয়ের সময়সীমা চলাকালীন, কোনও রানিং স্ক্রিপ্টের মধ্যে সিঙ্ক্রোনাস স্টাইল রিক্যালকুলেশন (যেমন, DOM মিউটেশনের পরে getComputedStyle() কল করা) এবং ফোর্সড লেআউট/রিফ্লো (যেমন, মিউটেশনের পরে getBoundingClientRect() বা offsetWidth রিড করা) রিপোর্ট করে।
  • ফ্রেম-লেভেল রেন্ডারিং স্টাইল ও লেআউট (styleDuration ও layoutDuration): ফ্রেমের রেন্ডারিং আপডেট করার সময় স্টাইল আবার গণনা করা বনাম লেআউট আপডেট করার জন্য ব্যয় করা সময়ের রিপোর্ট করে, যা বেশি প্রেজেন্টেশন বিলম্ব ব্যাখ্যা করতে সাহায্য করে।

লেআউট থেকে স্টাইল রিক্যালকুলেশন আলাদা করা অত্যন্ত গুরুত্বপূর্ণ কারণ তাদের বিভিন্ন মূল কারণ এবং সমাধান রয়েছে: হাই স্টাইল ডিউরেশন ব্যয়বহুল CSS সিলেক্টর ম্যাচিং বা ব্রড স্টাইল ইনভ্যালিডেশন (সিলেক্টর সহজ করে বা রুল স্কোপ কমিয়ে সমাধান করা হয়) নির্দেশ করে, যেখানে হাই লেআউট ডিউরেশন ব্যয়বহুল জ্যামিতি গণনা বা সিঙ্ক্রোনাস লেআউট থ্র্যাশিং (লেখার আগে DOM রিড ব্যাচিং করে, DOM স্ট্রাকচার সহজ করে বা CSS কন্টেনমেন্ট ব্যবহার করে সমাধান করা হয়) নির্দেশ করে।

কীভাবে প্রয়োগ করতে হয়

র' Event Timing API থেকে INP গণনা করা জটিল এবং এতে বেশ কিছু সূক্ষ্ম পার্থক্য রয়েছে। এই ডেটা সংগ্রহ করার জন্য আপনাকে RUM টুল বা লাইব্রেরি ব্যবহার করার পরামর্শ দেওয়া হচ্ছে।

web-vitals হল Google-এর একটি ওপেন-সোর্স লাইব্রেরি যা INP সহ Core Web Vitals গণনা করে এবং INP ইন্টার‍্যাকশনের জন্য সাবপার্ট এবং লং অ্যানিমেশন ফ্রেম ডেটাও অন্তর্ভুক্ত করে।

web-vitals লাইব্রেরি ব্যবহার করে INP ইন্টার‍্যাকশনের জন্য অ্যাট্রিবিউশন পান

web-vitals লাইব্রেরি হল একটি ছোট লাইব্রেরি যা Core Web Vitals এবং অন্যান্য পারফর্ম্যান্স মেট্রিক পরিমাপ করতে ব্যবহৃত হয়। onINP() ফাংশনটি সবচেয়ে ধীর ইন্টার‍্যাকশন শনাক্ত করতে ব্যবহার করা যেতে পারে এবং এতে INP সাবপার্ট, ইন্টার‍্যাকশনের সময় এক্সিকিউট করা স্ক্রিপ্ট এবং লং অ্যানিমেশন ফ্রেম API ব্যবহার করে স্টাইল ও লেআউটের সময়সীমা সম্পর্কিত তথ্য অন্তর্ভুক্ত থাকে।

// Use the attribution build to get Long Animation Frame data
// alongside the INP metric value.
import { onINP } from 'web-vitals/attribution';

onINP((metric) => {
  const { attribution } = metric;
  const longestScript = attribution.longestScript;

  // Sum rendering-phase style and layout durations across all LoAF entries
  // intersecting the INP interaction (primarily explains presentationDelay).
  let renderStyleDuration = 0;
  let renderLayoutDuration = 0;
  for (const entry of attribution.longAnimationFrameEntries) {
    renderStyleDuration += entry.styleDuration ?? 0;
    renderLayoutDuration += entry.layoutDuration ?? 0;
  }

  // Beacon script, style, and layout attribution for the INP interaction,
  // so you can identify the root cause in production.
  navigator.sendBeacon(
    '/analytics',
    JSON.stringify({
      name: 'INP',
      value: metric.value,
      // These fields give the INP subparts:
      inputDelay: attribution.inputDelay,
      presentationDelay: attribution.presentationDelay,
      processingDuration: attribution.processingDuration,
      interactionTarget: attribution.interactionTarget,
      // These fields identify which script function was responsible
      // for the longest processing during the INP interaction.
      invokerType: longestScript?.entry?.invokerType,
      sourceURL: longestScript?.entry?.sourceURL,
      sourceFunctionName: longestScript?.entry?.sourceFunctionName,
      sourceCharPosition: longestScript?.entry?.sourceCharPosition,
      // subpart indicates which phase (input delay, processing, or
      // presentation delay) the longest script overlapped with most.
      subpart: longestScript?.subpart,
      intersectingDuration: longestScript?.intersectingDuration,
      // Synchronous style and layout work forced inside the longest script
      // (with forcedStyleAndLayoutDuration as a combined fallback):
      forcedStyleDuration: longestScript?.entry?.forcedStyleDuration,
      forcedLayoutDuration: longestScript?.entry?.forcedLayoutDuration,
      forcedStyleAndLayoutDuration: longestScript?.entry?.forcedStyleAndLayoutDuration,
      // Rendering-phase style and layout work across the interaction's frames
      // (with totalStyleAndLayoutDuration as a combined fallback):
      renderStyleDuration,
      renderLayoutDuration,
      totalStyleAndLayoutDuration: attribution.totalStyleAndLayoutDuration
    })
  );
});

পেশাদার পদ্ধতি

  • ডিলেটি আগে থেকেই চলছে এমন জাভাস্ক্রিপ্ট (ইনপুট ডিলে), ইন্টার‍্যাকশনের জন্য ইভেন্ট হ্যান্ডলার জাভাস্ক্রিপ্ট (প্রসেসিংয়ের সময়সীমা) নাকি পরবর্তী রেন্ডারিং (প্রেজেন্টেশন ডিলে) তা শনাক্ত করতে প্রাথমিকভাবে INP সাবপার্ট ব্যবহার করুন।
  • অতিরিক্ত বিবরণ হিসেবে সবচেয়ে বড় ব্লকিং জাভাস্ক্রিপ্ট শনাক্ত করার চেষ্টা করুন, বিশেষ করে ইনপুট বিলম্ব ও প্রসেসিংয়ের সময়সীমার জন্য।
  • প্রসেসিংয়ের জন্য বেশি সময় লাগা বা প্রেজেন্টেশনে দেরি হওয়ার কারণ ডায়াগনসিস করার সময় স্টাইল রিক্যালকুলেশন (styleDuration, forcedStyleDuration) এবং লেআউটের (layoutDuration, forcedLayoutDuration) মধ্যে পার্থক্য করুন: স্টাইল রিক্যালকুলেশনের জন্য বেশি সময় লাগলে বুঝতে হবে যে CSS সিলেক্টর অনেক বেশি বা অনেক বেশি ইনভ্যালিডেশন আছে, অন্যদিকে লেআউটের জন্য বেশি সময় লাগলে বুঝতে হবে যে DOM জিওমেট্রি সংক্রান্ত সমস্যা বা সিঙ্ক্রোনাস লেআউট থ্র্যাশিংয়ের সমস্যা আছে।
  • JS সেল্ফ-প্রোফাইলিং API-এর মতো বিকল্পের পরিবর্তে এই আরও বিবরণ প্রদান করার জন্য লং অ্যানিমেশন ফ্রেম API-কে অগ্রাধিকার দিন, যা বেশি রানটাইম ওভারহেড বহন করে।
  • অন্য কোনও RUM সমাধান না থাকলে web-vitals লাইব্রেরি ব্যবহার করুন। এটি INP ইন্টার‍্যাকশন শনাক্ত করতে পারে এবং ইন্টার‍্যাকশনের সময় এক্সিকিউট করা সাবপার্ট ও স্ক্রিপ্ট সম্পর্কে তথ্য অন্তর্ভুক্ত করে (লং অ্যানিমেশন ফ্রেম API ব্যবহার করে)।
  • প্রয়োজনীয় তথ্য শুধু লোকাল স্টোরেজে লগ করার পরিবর্তে অ্যানালিটিক্স পরিষেবায় বিকন ব্যাক করুন।

ব্রাউজার সাপোর্ট ও ফলব্যাক স্ট্র্যাটেজি

Event Timing API বেশিরভাগ আধুনিক ব্রাউজারে উপলভ্য এবং INP ও INP সাবপার্ট গণনা করার জন্য এটি প্রয়োজন। যেসব ব্রাউজারে এই API কাজ করে না, সেখানে INP পরিমাপ করা যায় না।

লং অ্যানিমেশন ফ্রেম API ঐচ্ছিক, অতিরিক্ত বিবরণ প্রদান করে। এটি ফলব্যাক ছাড়াই নিরাপদে ব্যবহার করা যেতে পারে। বেশিরভাগ ক্ষেত্রে, এটি যে পারফর্ম্যান্সের সুযোগ শনাক্ত করে তা অন্যান্য ব্রাউজারের ক্ষেত্রেও প্রযোজ্য হবে।

আপনার বেসলাইন টার্গেটে লং অ্যানিমেশন ফ্রেম API (long-animation-frames) কাজ করলেও আলাদা স্টাইল ও লেআউট ডিউরেশন প্রপার্টি (PerformanceLongAnimationFrameTiming-এ styleDuration ও layoutDuration অথবা PerformanceScriptTiming-এ forcedStyleDuration ও forcedLayoutDuration) কাজ না করলে, কম্বাইন করা স্টাইল-ও-লেআউট টাইমিংয়ে ফিরে যান:

  • স্ক্রিপ্টের মধ্যে সিঙ্ক্রোনাস ফোর্সড স্টাইল এবং লেআউট কাজের জন্য PerformanceScriptTiming-এ script.forcedStyleAndLayoutDuration ব্যবহার করুন।
  • স্টাইল ও লেআউট সংক্রান্ত কাজ একসাথে করার জন্য web-vitals/attribution-এ metric.attribution.totalStyleAndLayoutDuration ব্যবহার করুন (অথবা প্রতিটি PerformanceLongAnimationFrameTiming এন্ট্রিতে (entry.paintTime || entry.startTime + entry.duration) - entry.styleAndLayoutStart গণনা করুন)।