اندازه گیری تعامل با رنگ بعدی (INP)، اندازه گیری تعامل با رنگ بعدی (INP)

۱. مقدمه

این یک آزمایشگاه کد تعاملی برای یادگیری نحوه اندازه‌گیری تعامل با رنگ بعدی (INP) با استفاده از کتابخانه web-vitals است.

پیش‌نیازها

آنچه یاد خواهید گرفت

  • نحوه اضافه کردن کتابخانه web-vitals به صفحه خود و استفاده از داده‌های انتساب آن.
  • از داده‌های انتساب برای تشخیص اینکه از کجا و چگونه می‌توان بهبود INP را شروع کرد، استفاده کنید.

آنچه شما نیاز خواهید داشت

  • رایانه‌ای با قابلیت کپی کردن کد از گیت‌هاب و اجرای دستورات npm.
  • یک ویرایشگر متن.
  • نسخه جدیدی از کروم برای کار کردن تمام معیارهای تعامل.

۲. آماده شوید

دریافت و اجرای کد

این کد در مخزن web-vitals-codelabs یافت می‌شود.

  1. مخزن را در ترمینال خود کپی کنید: git clone https://github.com/GoogleChromeLabs/web-vitals-codelabs.git .
  2. به دایرکتوری کلون شده بروید: cd web-vitals-codelabs/measuring-inp .
  3. نصب وابستگی‌ها: npm ci .
  4. شروع سرور وب: npm run start .
  5. در مرورگر خود به آدرس http://localhost:8080/ مراجعه کنید.

صفحه را امتحان کنید

این آزمایشگاه کد از Gastropodicon (یک سایت مرجع محبوب آناتومی حلزون) برای بررسی مشکلات احتمالی INP استفاده می‌کند.

تصویری از صفحه آزمایشی Gastropodicon

سعی کنید با صفحه تعامل داشته باشید تا متوجه شوید کدام تعاملات کند هستند.

۳. قرار گرفتن در Chrome DevTools

DevTools را از منوی More Tools > Developer Tools ، با کلیک راست روی صفحه و انتخاب Inspect یا با استفاده از میانبر صفحه‌کلید ، باز کنید.

در این آزمایشگاه کد، ما از هر دو پنل Performance و Console استفاده خواهیم کرد. می‌توانید در هر زمان بین این پنل‌ها در تب‌های بالای DevTools جابجا شوید.

  • مشکلات INP اغلب در دستگاه‌های تلفن همراه رخ می‌دهد، بنابراین به شبیه‌سازی صفحه نمایش تلفن همراه بروید .
  • اگر روی دسکتاپ یا لپ‌تاپ تست می‌کنید، عملکرد احتمالاً به طور قابل توجهی بهتر از یک دستگاه تلفن همراه واقعی خواهد بود. برای نگاهی واقع‌بینانه‌تر به عملکرد، روی چرخ‌دنده در سمت راست بالای پنل Performance کلیک کنید، سپس CPU 4x slowdown را انتخاب کنید.

تصویری از پنل عملکرد DevTools در کنار برنامه، با انتخاب گزینه کاهش سرعت پردازنده تا ۴ برابر

۴. نصب موارد حیاتی وب

web-vitals یک کتابخانه جاوا اسکریپت برای اندازه‌گیری معیارهای Web Vitals است که کاربران شما تجربه می‌کنند. می‌توانید از این کتابخانه برای ثبت این مقادیر استفاده کنید و سپس آنها را برای تجزیه و تحلیل‌های بعدی به یک نقطه پایانی تجزیه و تحلیل ارسال کنید، تا بتوانیم بفهمیم چه زمانی و کجا تعاملات کند رخ می‌دهد.

چند روش مختلف برای افزودن کتابخانه به یک صفحه وجود دارد. نحوه نصب کتابخانه در سایت شما به نحوه مدیریت وابستگی‌ها، فرآیند ساخت و سایر عوامل بستگی دارد. حتماً اسناد کتابخانه را برای همه گزینه‌های خود بررسی کنید.

این codelab از npm نصب می‌شود و اسکریپت را مستقیماً بارگذاری می‌کند تا از درگیر شدن در یک فرآیند ساخت خاص جلوگیری شود.

دو نسخه از web-vitals وجود دارد که می‌توانید از آنها استفاده کنید:

  • اگر می‌خواهید مقادیر متریک Core Web Vitals را در بارگذاری صفحه ردیابی کنید، باید از نسخه «استاندارد» استفاده کنید.
  • ساختار «attribution» اطلاعات اشکال‌زدایی اضافی را به هر معیار اضافه می‌کند تا تشخیص دهد که چرا یک معیار در نهایت به این مقدار می‌رسد.

برای اندازه‌گیری INP در این آزمایشگاه کد، به ساختار Attribution نیاز داریم.

با اجرای دستور npm install -D web-vitals web-vitals به devDependencies پروژه اضافه کنید.

web-vitals به صفحه اضافه کنید:

نسخه مربوط به اسکریپت را به انتهای index.html اضافه کنید و نتایج را در کنسول ثبت کنید:

<script type="module">
  import {onINP} from './node_modules/web-vitals/dist/web-vitals.attribution.js';

  onINP(console.log);
</script>

امتحانش کن.

دوباره با کنسول باز، سعی کنید با صفحه تعامل داشته باشید. همانطور که در صفحه کلیک می‌کنید، هیچ چیزی ثبت نمی‌شود!

INP در کل چرخه عمر یک صفحه اندازه‌گیری می‌شود، بنابراین به‌طور پیش‌فرض، web-vitals تا زمانی که کاربر صفحه را ترک یا بسته نکند، INP را گزارش نمی‌کند. این رفتار ایده‌آل برای راهنمایی در مواردی مانند تجزیه و تحلیل است، اما برای اشکال‌زدایی تعاملی چندان ایده‌آل نیست.

web-vitals گزینه reportAllChanges را برای گزارش‌های مفصل‌تر ارائه می‌دهد. وقتی فعال باشد، هر تعاملی گزارش نمی‌شود، اما هر بار که تعاملی کندتر از قبلی باشد، گزارش می‌شود.

سعی کنید این گزینه را به اسکریپت اضافه کنید و دوباره با صفحه تعامل داشته باشید:

<script type="module">
  import {onINP} from './node_modules/web-vitals/dist/web-vitals.attribution.js';

  onINP(console.log, {reportAllChanges: true});
</script>

صفحه را رفرش کنید. حالا باید تعاملات به کنسول گزارش شوند و هر زمان که کندترین مورد جدیدی وجود داشته باشد، به‌روزرسانی شوند. برای مثال، سعی کنید در کادر جستجو تایپ کنید و سپس ورودی را حذف کنید.

تصویری از کنسول DevTools که پیام‌های INP با موفقیت در آن چاپ شده‌اند

۵. چه چیزهایی در انتساب وجود دارد؟

بیایید با اولین تعاملی که اکثر کاربران با صفحه دارند، یعنی پنجره‌ی رضایت کوکی، شروع کنیم.

بسیاری از صفحات اسکریپت‌هایی دارند که نیاز دارند کوکی‌ها همزمان با پذیرش کوکی‌ها توسط کاربر فعال شوند و باعث می‌شوند کلیک به یک تعامل کند تبدیل شود. این همان اتفاقی است که اینجا می‌افتد.

برای پذیرش کوکی‌ها (دمو) روی بله کلیک کنید و نگاهی به داده‌های INP که اکنون در کنسول DevTools ثبت شده‌اند، بیندازید.

شیء داده INP که در کنسول DevTools ثبت شده است

این اطلاعات سطح بالا هم در نسخه استاندارد و هم در نسخه‌های وب ویتال Attribution موجود است:

{
  name: 'INP',
  value: 344,
  rating: 'needs-improvement',
  entries: [...],
  id: 'v4-1715732159298-8028729544485',
  navigationType: 'reload',
  attribution: {...},
}

مدت زمان شروع از زمانی که کاربر روی رنگ بعدی کلیک می‌کند، ۳۴۴ میلی‌ثانیه بود - یک INP «نیاز به بهبود» . آرایه entries تمام مقادیر PerformanceEntry مرتبط با این تعامل را دارد - در این مورد، فقط یک رویداد کلیک.

با این حال، برای فهمیدن اینکه در این مدت چه اتفاقی می‌افتد، ما بیشتر به ویژگی attribution علاقه‌مند هستیم. برای ساخت داده‌های 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 : یک ارجاع زنده به عنصری که با آن تعامل صورت گرفته است (اگر عنصر از DOM حذف نشده باشد).
  • interactionTarget : یک انتخابگر برای یافتن عنصر درون صفحه.

در مرحله بعد، زمان‌بندی به صورت سطح بالا تجزیه می‌شود:

  • inputDelay : زمان بین زمانی که کاربر تعامل را شروع می‌کند (مثلاً کلیک ماوس) و زمانی که شنونده رویداد برای آن تعامل شروع به اجرا می‌کند. در این حالت، تأخیر ورودی حتی با فعال بودن تنظیم سرعت پردازنده، تنها حدود ۲۷ میلی‌ثانیه بود.
  • processingDuration : مدت زمانی که طول می‌کشد تا شنونده‌های رویداد اجرا شوند و به پایان برسند. اغلب، صفحات برای یک رویداد واحد چندین شنونده دارند (برای مثال، pointerdown ، pointerup و click ). اگر همه آنها در یک فریم انیمیشن اجرا شوند، در این زمان ادغام می‌شوند. در این حالت، مدت زمان پردازش ۲۹۵.۶ میلی‌ثانیه طول می‌کشد - بخش عمده‌ای از زمان INP.
  • presentationDelay ): مدت زمان از زمانی که شنونده‌های رویداد (event listeners) کار خود را تمام کرده‌اند تا زمانی که مرورگر نقاشی فریم بعدی را تمام کرده است. در این مورد، ۲۱.۴ میلی‌ثانیه.

این مراحل INP می‌توانند یک سیگنال حیاتی برای تشخیص آنچه که نیاز به بهینه‌سازی دارد، باشند. راهنمای Optimize INP اطلاعات بیشتری در این مورد دارد .

با کمی بررسی عمیق‌تر، متوجه می‌شویم که processedEventEntries شامل پنج رویداد است، برخلاف یک رویداد واحد در آرایه entries INP سطح بالا. تفاوت چیست؟

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: [{...}]
}],

تعدادی مقدار مفید در اینجا وجود دارد، مانند نمایش میزان زمان صرف شده برای استایل‌بندی. مقاله‌ی Long Animation Frames API به طور عمیق‌تری به این ویژگی‌ها می‌پردازد . در حال حاضر ما در درجه‌ی اول به ویژگی 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
}]

در این حالت، می‌توانیم بگوییم که زمان عمدتاً در یک event-listener واحد که در BUTTON#confirm.onclick فراخوانی شده است، صرف شده است. ما حتی می‌توانیم URL منبع اسکریپت و موقعیت کاراکتری محل تعریف تابع را ببینیم!

غذای بیرون‌بر

از این داده‌های انتساب چه چیزی می‌توان در مورد این پرونده مشخص کرد؟

  • این تعامل با کلیک روی عنصر button#confirm (از attribution.interactionTarget و ویژگی invoker در یک ورودی script attribution) آغاز شد.
  • زمان صرف شده عمدتاً صرف اجرای شنونده‌های رویداد (از attribution.processingDuration در مقایسه با value کل معیار) شده است.
  • کد شنونده رویداد slow از یک شنونده کلیک که در third-party/cmp.js (از scripts.sourceURL ) تعریف شده است، شروع می‌شود.

این داده‌ها برای دانستن اینکه کجا باید بهینه‌سازی کنیم، کافی است!

۶. چندین شنونده رویداد

صفحه را رفرش کنید تا کنسول 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: [...],
  }
}

این یک مقدار INP ضعیف (با فعال بودن قابلیت تنظیم سرعت پردازنده) از تعامل صفحه کلید با عنصر input#search-terms است. بخش عمده زمان - ۱۰۶۱ میلی ثانیه از کل INP 1072 میلی ثانیه - صرف مدت زمان پردازش شده است.

با این حال، نوشته‌های 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 . این مدت زمانی بود که در این فراخوانی اسکریپت صرف می‌شد، جایی که مرورگر مجبور به رله کردن صفحه می‌شد. به عبارت دیگر، ۷۸٪ از زمانی که صرف اجرای این شنونده رویداد شد - ۳۸۸ میلی‌ثانیه از ۴۹۷ میلی‌ثانیه - در واقع صرف بارگذاری مجدد طرح‌بندی شد.

این باید اولویت اصلی برای رفع مشکل باشد.

شنوندگان مکرر

به طور جداگانه، هیچ چیز قابل توجه خاصی در مورد دو نوشته فیلمنامه بعدی وجود ندارد:

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 گزارش نمی‌شود)، اما ما هنوز یک فایل منبع و موقعیت کاراکتر داریم، بنابراین می‌توانیم بفهمیم کد کجا قرار دارد.

نکته عجیب این است که هر دو از یک فایل منبع و موقعیت کاراکتری یکسان هستند .

مرورگر در نهایت چندین بار فشردن کلید را در یک فریم انیمیشن پردازش کرد، که منجر به اجرای دو باره‌ی این شنونده‌ی رویداد قبل از اینکه چیزی نقاشی شود، شد!

این اثر می‌تواند تشدید هم بشود، هر چه تکمیل شنونده‌های رویداد بیشتر طول بکشد، رویدادهای ورودی بیشتری می‌توانند وارد شوند و این تعامل کند را بسیار طولانی‌تر می‌کند.

از آنجایی که این یک تعامل جستجو/تکمیل خودکار است، حذف ورودی می‌تواند استراتژی خوبی باشد تا حداکثر، در هر فریم یک کلید فشرده شده پردازش شود.

۷. تأخیر ورودی

دلیل معمول تأخیر ورودی - مدت زمانی که از زمان تعامل کاربر تا زمانی که یک شنونده رویداد می‌تواند پردازش تعامل را شروع کند - مشغول بودن نخ اصلی است. این می‌تواند دلایل مختلفی داشته باشد:

  • صفحه در حال بارگذاری است و رشته اصلی (main thread) مشغول انجام کارهای اولیه تنظیم DOM، طرح‌بندی و استایل‌دهی صفحه و ارزیابی و اجرای اسکریپت‌ها است.
  • صفحه معمولاً شلوغ است - برای مثال، در حال اجرای محاسبات، انیمیشن‌های مبتنی بر اسکریپت یا تبلیغات.
  • پردازش تعاملات قبلی آنقدر طول می‌کشد که تعاملات آینده را به تأخیر می‌اندازد، همانطور که در مثال آخر مشاهده شد.

صفحه دمو یک ویژگی مخفی دارد که اگر روی لوگوی حلزون در بالای صفحه کلیک کنید، شروع به انیمیشن‌سازی و انجام برخی کارهای سنگین جاوااسکریپت در thread اصلی می‌کند.

  • برای شروع انیمیشن روی لوگوی حلزون کلیک کنید.
  • وظایف جاوا اسکریپت زمانی فعال می‌شوند که حلزون در پایین‌ترین نقطه پرش قرار دارد. سعی کنید تا حد امکان نزدیک به پایین‌ترین نقطه پرش با صفحه تعامل داشته باشید و ببینید چه مقدار از INP را می‌توانید فعال کنید.

برای مثال، حتی اگر هیچ شنونده رویداد دیگری را فعال نکنید - مثلاً با کلیک کردن و فوکوس کردن روی کادر جستجو درست هنگام پرش حلزون - کار نخ اصلی باعث می‌شود صفحه برای مدت زمان قابل توجهی پاسخگو نباشد.

در بسیاری از صفحات، کارهای سنگین مربوط به نخ اصلی به این خوبی انجام نمی‌شوند، اما این مثال خوبی برای مشاهده‌ی چگونگی قابل شناسایی بودن آن در داده‌های انتساب 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: [{...}]
    }]
  }
}

همانطور که پیش‌بینی می‌شد، شنونده‌های رویداد به سرعت اجرا شدند - مدت زمان پردازش ۴.۹ میلی‌ثانیه را نشان دادند و بخش عمده‌ای از این تعامل ضعیف صرف تأخیر ورودی شد که ۷۰۲.۳ میلی‌ثانیه از مجموع ۷۲۸ را به خود اختصاص داد.

اشکال‌زدایی این وضعیت می‌تواند دشوار باشد. اگرچه می‌دانیم کاربر با چه چیزی و چگونه تعامل داشته است، اما می‌دانیم که آن بخش از تعامل به سرعت تکمیل شده و مشکلی نبوده است. در عوض، چیز دیگری در صفحه بوده که تعامل را از شروع پردازش به تأخیر انداخته است، اما چگونه می‌دانیم که از کجا شروع به جستجو کنیم؟

ورودی‌های اسکریپت 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 )، دقیقاً کدام تابع مسئول بوده و در کجای فایل‌های منبع ما قرار داشته است.

۸. تأخیر در ارائه: وقتی به‌روزرسانی اجرا نمی‌شود

تأخیر ارائه، مدت زمانی را اندازه‌گیری می‌کند که از زمان پایان اجرای شنونده‌های رویداد تا زمانی که مرورگر قادر به ترسیم یک فریم جدید روی صفحه باشد و بازخورد قابل مشاهده را به کاربر نشان دهد، طول می‌کشد.

صفحه را رفرش کنید تا مقدار 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: [{...}]
    }]
  }
}

این بار، تأخیر در ارائه است که بخش عمده‌ای از کندی تعامل را تشکیل می‌دهد. این بدان معناست که هر چیزی که مانع از اجرای thread اصلی می‌شود، پس از اتمام اجرای event listeners رخ می‌دهد.

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 ، می‌بینیم که زمان صرف شده در یک user-callback از FrameRequestCallback است. این بار تأخیر در ارائه توسط یک فراخوانی requestAnimationFrame ایجاد شده است.

۹. نتیجه‌گیری

تجمیع داده‌های میدانی

شایان ذکر است که این کار وقتی که به یک ورودی انتساب INP از یک صفحه واحد نگاه می‌کنید، آسان‌تر است. چگونه می‌توان این داده‌ها را برای اشکال‌زدایی INP بر اساس داده‌های میدانی تجمیع کرد؟ میزان جزئیات مفید در واقع این کار را دشوارتر می‌کند.

برای مثال، دانستن اینکه کدام عنصر صفحه منبع مشترک کندی تعاملات است، بسیار مفید است. با این حال، اگر صفحه شما نام کلاس‌های CSS کامپایل شده‌ای دارد که از ساختی به ساخت دیگر تغییر می‌کنند، انتخابگرهای web-vitals از یک عنصر ممکن است در ساخت‌های مختلف متفاوت باشند.

در عوض، شما باید به کاربرد خاص خود فکر کنید تا مشخص کنید چه چیزی مفیدتر است و چگونه می‌توان داده‌ها را جمع‌آوری کرد. به عنوان مثال، قبل از ارسال داده‌های ارجاع، می‌توانید انتخابگر web-vitals را با یک شناسه خودتان جایگزین کنید، بر اساس مؤلفه‌ای که هدف در آن قرار دارد یا نقش‌های ARIA که هدف ایفا می‌کند.

به طور مشابه، ورودی‌های scripts ممکن است در مسیرهای sourceURL خود دارای هش‌های مبتنی بر فایل باشند که ترکیب آنها را دشوار می‌کند، اما می‌توانید هش‌ها را بر اساس فرآیند ساخت شناخته شده خود قبل از ارسال مجدد داده‌ها، حذف کنید.

متأسفانه، با داده‌هایی به این پیچیدگی، هیچ مسیر آسانی وجود ندارد، اما حتی استفاده از زیرمجموعه‌ای از آن، برای فرآیند اشکال‌زدایی، ارزشمندتر از نداشتن هیچ داده‌ی انتسابی است.

انتساب در همه جا!

انتساب INP مبتنی بر 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);

بیشتر بدانید