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

1. معرفی

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

پیش نیازها

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

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

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

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

2. راه اندازی شوید

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

کد در مخزن 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

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

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

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

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

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

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

4. نصب وب ویتال

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

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

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

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

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

برای اندازه گیری INP در این کد لبه، ما می خواهیم ساخت انتساب.

با اجرای 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 را گزارش نمی کند تا زمانی که کاربر صفحه را ترک کند یا آن را ببندد. این رفتار ایده آل برای beaconing برای چیزی مانند تجزیه و تحلیل است، اما برای اشکال زدایی تعاملی کمتر ایده آل است.

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 که با موفقیت در آن چاپ شده است

5. در یک انتساب چیست؟

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

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

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

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

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

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

مدت زمان شروع از کلیک کاربر تا رنگ بعدی 344 میلی ثانیه بود - INP "نیاز به بهبود دارد" . آرایه entries دارای تمام مقادیر PerformanceEntry مرتبط با این تعامل است - در این مورد، رویداد فقط با یک کلیک.

با این حال، برای اینکه بفهمیم در این مدت چه می‌گذرد، ما بیشتر به ویژگی 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 : زمان بین زمانی که کاربر تعامل را شروع کرد (مثلاً روی ماوس کلیک کرد) و زمانی که شنونده رویداد برای آن تعامل شروع به اجرا کرد. در این مورد، تاخیر ورودی تنها حدود 27 میلی ثانیه بود، حتی با روشن بودن گاز CPU.
  • processingDuration : مدت زمانی که طول می کشد تا شنوندگان رویداد اجرا شوند. اغلب، صفحات چندین شنونده برای یک رویداد واحد دارند (به عنوان مثال، pointerdown ، pointerup و click ). اگر همه آنها در یک قاب انیمیشن اجرا شوند، در این زمان ادغام می شوند. در این مورد، مدت زمان پردازش 295.6 میلی ثانیه طول می کشد - بخش عمده ای از زمان INP.
  • presentationDelay : زمانی از زمانی که شنوندگان رویداد کامل می‌شوند تا زمانی که مرورگر نقاشی فریم بعدی را به پایان می‌رساند. در این حالت 21.4 میلی ثانیه.

این فازهای 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 است، در این مورد یک کلیک. Attribution 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 در ورودی انتساب اسکریپت) آغاز شد.
  • زمان عمدتاً صرف اجرای شنوندگان رویداد (از attribution.processingDuration در مقایسه با value کل متریک) شد.
  • کد شنونده رویداد آهسته از یک شنونده کلیکی تعریف شده در third-party/cmp.js (از scripts.sourceURL ) شروع می شود.

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

6. شنوندگان رویدادهای متعدد

صفحه را بازخوانی کنید تا کنسول 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 ضعیف (با فعال کردن throttling CPU) ناشی از تعامل صفحه کلید با عنصر input#search-terms است. بیشتر زمان - 1061 میلی ثانیه از 1072 میلی ثانیه کل INP - در مدت زمان پردازش صرف شد.

با این حال، ورودی‌های 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 است (Invoker INPUT#search-terms.oninput است). نام تابع داده شده است ( handleSearch )، همانطور که موقعیت کاراکتر در فایل منبع index.js نیز وجود دارد.

اما یک ویژگی جدید وجود دارد: forcedStyleAndLayoutDuration . این زمانی بود که در این فراخوانی اسکریپت سپری شد و مرورگر مجبور شد صفحه را تغییر دهد. به عبارت دیگر، 78٪ از زمان - 388 میلی ثانیه از 497 - برای اجرای این شنونده رویداد در واقع در تراشه کردن طرح سپری شده است.

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

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

به طور جداگانه، هیچ چیز قابل توجهی در مورد دو ورودی اسکریپت بعدی وجود ندارد:

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

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

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

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

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

7. تاخیر ورودی

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

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

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

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

همانطور که پیش‌بینی می‌شد، شنوندگان رویداد به سرعت اجرا می‌شدند – با نشان دادن مدت زمان پردازش 4.9 میلی‌ثانیه، و اکثریت قریب به اتفاق تعامل ضعیف در تأخیر ورودی صرف شد، که 702.3 میلی‌ثانیه از مجموع 728 را گرفت.

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

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

8. تأخیر ارائه: زمانی که یک به روز رسانی فقط رنگ نمی کند

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

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

این بار تأخیر ارائه است که اکثریت تعامل آهسته را تشکیل می دهد. این بدان معناست که هر چیزی که موضوع اصلی را مسدود می کند، پس از اتمام شنوندگان رویداد رخ می دهد.

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 است.

9. نتیجه گیری

جمع آوری داده های میدانی

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

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

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

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

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

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

اسناد INP مبتنی بر LoAF یک کمک عیب‌یابی قدرتمند است. این داده‌های ریز در مورد آنچه به طور خاص در طول یک INP اتفاق افتاده را ارائه می‌دهد. در بسیاری از موارد، می تواند مکان دقیق یک اسکریپت را به شما نشان دهد که در آن باید تلاش های بهینه سازی خود را شروع کنید.

اکنون آماده استفاده از داده های انتساب INP در هر سایتی هستید!

حتی اگر به ویرایش یک صفحه دسترسی ندارید، می‌توانید با اجرای قطعه زیر در کنسول DevTools، فرآیند را از این Codelab دوباره ایجاد کنید تا ببینید چه چیزی می‌توانید پیدا کنید:

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

بیشتر بدانید

،

1. معرفی

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

پیش نیازها

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

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

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

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

2. راه اندازی شوید

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

کد در مخزن 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

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

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

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

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

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

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

4. نصب وب ویتال

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

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

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

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

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

برای اندازه گیری INP در این کد لبه، ما می خواهیم ساخت انتساب.

با اجرای 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 را گزارش نمی کند تا زمانی که کاربر صفحه را ترک کند یا آن را ببندد. این رفتار ایده آل برای beaconing برای چیزی مانند تجزیه و تحلیل است، اما برای اشکال زدایی تعاملی کمتر ایده آل است.

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 که با موفقیت در آن چاپ شده است

5. در یک انتساب چیست؟

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

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

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

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

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

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

مدت زمان شروع از کلیک کاربر تا رنگ بعدی 344 میلی ثانیه بود - INP "نیاز به بهبود دارد" . آرایه entries دارای تمام مقادیر PerformanceEntry مرتبط با این تعامل است - در این مورد، رویداد فقط با یک کلیک.

با این حال، برای اینکه بفهمیم در این مدت چه می‌گذرد، ما بیشتر به ویژگی 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 : زمان بین زمانی که کاربر تعامل را شروع کرد (مثلاً روی ماوس کلیک کرد) و زمانی که شنونده رویداد برای آن تعامل شروع به اجرا کرد. در این مورد، تاخیر ورودی تنها حدود 27 میلی ثانیه بود، حتی با روشن بودن گاز CPU.
  • processingDuration : مدت زمانی که طول می کشد تا شنوندگان رویداد اجرا شوند. اغلب، صفحات چندین شنونده برای یک رویداد واحد دارند (به عنوان مثال، pointerdown ، pointerup ، و click ). اگر همه آنها در یک قاب انیمیشن اجرا شوند، در این زمان ادغام می شوند. در این مورد، مدت زمان پردازش 295.6 میلی ثانیه طول می کشد - بخش عمده ای از زمان INP.
  • presentationDelay : زمانی از زمانی که شنوندگان رویداد کامل می‌شوند تا زمانی که مرورگر نقاشی فریم بعدی را به پایان می‌رساند. در این حالت 21.4 میلی ثانیه.

این فازهای 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 است، در این مورد یک کلیک. Attribution 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 در ورودی انتساب اسکریپت) آغاز شد.
  • زمان عمدتاً صرف اجرای شنوندگان رویداد (از attribution.processingDuration در مقایسه با value کل متریک) شد.
  • کد شنونده رویداد آهسته از یک شنونده کلیکی تعریف شده در third-party/cmp.js (از scripts.sourceURL ) شروع می شود.

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

6. شنوندگان رویدادهای متعدد

صفحه را بازخوانی کنید تا کنسول 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 ضعیف (با فعال کردن throttling CPU) ناشی از تعامل صفحه کلید با عنصر input#search-terms است. بیشتر زمان - 1061 میلی ثانیه از 1072 میلی ثانیه کل INP - در مدت زمان پردازش صرف شد.

با این حال، ورودی‌های 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 است (Invoker INPUT#search-terms.oninput است). نام تابع داده شده است ( handleSearch )، همانطور که موقعیت کاراکتر در فایل منبع index.js نیز وجود دارد.

اما یک ویژگی جدید وجود دارد: forcedStyleAndLayoutDuration . این زمانی بود که در این فراخوانی اسکریپت سپری شد و مرورگر مجبور شد صفحه را تغییر دهد. به عبارت دیگر، 78٪ از زمان - 388 میلی ثانیه از 497 - برای اجرای این شنونده رویداد در واقع در تراشه کردن طرح سپری شده است.

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

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

به طور جداگانه، هیچ چیز قابل توجهی در مورد دو ورودی اسکریپت بعدی وجود ندارد:

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

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

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

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

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

7. تاخیر ورودی

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

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

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

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

همانطور که پیش‌بینی می‌شد، شنوندگان رویداد به سرعت اجرا می‌شدند – با نشان دادن مدت زمان پردازش 4.9 میلی‌ثانیه، و اکثریت قریب به اتفاق تعامل ضعیف در تأخیر ورودی صرف شد، که 702.3 میلی‌ثانیه از مجموع 728 را گرفت.

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

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

8. تأخیر در ارائه: هنگامی که به روزرسانی فقط نقاشی نمی شود

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

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

این بار تأخیر ارائه است که اکثر تعامل آهسته را تشکیل می دهد. این بدان معناست که هر آنچه که موضوع اصلی را مسدود می کند پس از اتمام شنوندگان رویداد رخ می دهد.

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 ایجاد می شود.

9. نتیجه گیری

جمع آوری داده های میدانی

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

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

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

به طور مشابه ، ورودی های scripts ممکن است در مسیرهای sourceURL خود که باعث ترکیب آنها می شود ، هش های مبتنی بر پرونده داشته باشند ، اما می توانید قبل از بازگشت داده ها ، هش ها را بر اساس فرآیند ساخت شناخته شده خود بچرخانید.

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

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

انتساب INP مبتنی بر LOAF یک کمک اشکال زدایی قدرتمند است. این داده های گرانول را در مورد آنچه که به طور خاص در طول INP اتفاق افتاده است ارائه می دهد. در بسیاری از موارد ، می تواند شما را به مکان دقیق در یک اسکریپت نشان دهد که باید تلاش های بهینه سازی خود را شروع کنید.

اکنون شما آماده استفاده از داده های انتساب INP در هر سایتی هستید!

حتی اگر به ویرایش یک صفحه دسترسی ندارید ، می توانید با اجرای قطعه زیر در کنسول DevTools ، فرآیند را از این CodeLab بازآفرینی کنید تا ببینید چه چیزی می توانید پیدا کنید:

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

بیشتر بدانید