بیاموزید که چگونه تعاملات آهسته را در داده های میدانی وب سایت خود پیدا کنید تا بتوانید فرصت هایی برای بهبود تعامل آن در Next Paint پیدا کنید.
دادههای میدانی دادههایی هستند که به شما میگویند کاربران واقعی وبسایت شما را چگونه تجربه میکنند. مشکلاتی را که نمی توانید به تنهایی در داده های آزمایشگاهی پیدا کنید، حل می کند. در مورد Interaction to Next Paint (INP) ، دادههای میدانی برای شناسایی تعاملات آهسته ضروری است و سرنخهای حیاتی برای کمک به رفع آنها ارائه میدهد.
در این راهنما، یاد خواهید گرفت که چگونه به سرعت INP وب سایت خود را با استفاده از داده های میدانی گزارش تجربه کاربر Chrome (CrUX) ارزیابی کنید تا ببینید آیا وب سایت شما با INP مشکل دارد یا خیر. متعاقباً، یاد خواهید گرفت که چگونه از ساخت اسناد کتابخانه جاوا اسکریپت web-vitals - و بینشهای جدیدی که از Long Animation Frames API (LoAF) ارائه میکند - برای جمعآوری و تفسیر دادههای میدانی برای تعاملات آهسته در وبسایت خود استفاده کنید.
برای ارزیابی INP وب سایت خود با CrUX شروع کنید
اگر اطلاعات میدانی را از کاربران وب سایت خود جمع آوری نمی کنید، CrUX ممکن است نقطه شروع خوبی باشد. CrUX داده های میدانی را از کاربران واقعی Chrome که ارسال داده های تله متری را انتخاب کرده اند جمع آوری می کند.
دادههای CrUX در تعدادی از مناطق مختلف ظاهر میشوند و این بستگی به دامنه اطلاعاتی دارد که به دنبال آن هستید. CrUX می تواند داده هایی را در مورد INP و دیگر Core Web Vitals برای موارد زیر ارائه دهد:
- صفحات منفرد و کل مبدا با استفاده از PageSpeed Insights .
- انواع صفحات. برای مثال، بسیاری از وبسایتهای تجارت الکترونیک دارای انواع صفحه جزئیات محصول و صفحه فهرست محصول هستند. میتوانید دادههای CrUX را برای انواع صفحات منحصربهفرد در کنسول جستجو دریافت کنید.
به عنوان نقطه شروع، می توانید URL وب سایت خود را در PageSpeed Insights وارد کنید. هنگامی که URL را وارد کردید، داده های فیلد مربوط به آن - در صورت وجود - برای چندین معیار از جمله INP نمایش داده می شود. همچنین می توانید از ضامن ها برای بررسی مقادیر INP خود برای ابعاد موبایل و دسکتاپ استفاده کنید.

این داده مفید است زیرا به شما می گوید که آیا مشکلی دارید. با این حال، کاری که CrUX نمی تواند انجام دهد این است که به شما بگوید چه چیزی باعث مشکلات می شود. راه حل های بسیاری برای نظارت بر کاربر واقعی (RUM) موجود است که به شما کمک می کند داده های میدانی خود را از کاربران وب سایت خود جمع آوری کنید تا به شما در پاسخ به آن کمک کند، و یک گزینه این است که خودتان آن داده های میدانی را با استفاده از کتابخانه JavaScript web-vitals جمع آوری کنید.
داده های میدانی را با کتابخانه جاوا اسکریپت web-vitals
جمع آوری کنید
کتابخانه جاوا اسکریپت web-vitals
یک اسکریپت است که می توانید برای جمع آوری داده های میدانی از کاربران وب سایت خود در وب سایت خود بارگذاری کنید. می توانید از آن برای ثبت تعدادی معیار از جمله INP در مرورگرهایی که از آن پشتیبانی می کنند استفاده کنید.
ساخت استاندارد کتابخانه web-vitals می تواند برای دریافت داده های اولیه INP از کاربران در این زمینه استفاده شود:
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 بیشتر بروید
ساختار اسناد کتابخانه web-vitals دادههای بیشتری را نشان میدهد که میتوانید از کاربران در این زمینه دریافت کنید تا به شما در عیبیابی بهتر تعاملات مشکلساز که بر INP وبسایت شما تأثیر میگذارند کمک کند. این داده ها از طریق شی attribution
ظاهر شده در روش onINP()
کتابخانه قابل دسترسی است:
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
});

علاوه بر خود INP صفحه، ساخت انتساب دادههای زیادی را ارائه میکند که میتوانید از آنها برای درک دلایل کندی تعامل استفاده کنید، از جمله اینکه باید روی کدام بخش از تعامل تمرکز کنید. می تواند به شما کمک کند به سوالات مهمی مانند:
- "آیا کاربر هنگام بارگیری صفحه با آن ارتباط برقرار کرده است؟"
- "آیا کنترل کننده های رویداد تعامل برای مدت طولانی اجرا می شدند؟"
- "آیا کد کنترل کننده رویداد تعامل با تاخیر شروع شده بود؟ اگر چنین است، در آن زمان چه چیز دیگری در رشته اصلی اتفاق می افتاد؟"
- "آیا این تعامل باعث رندر کار زیادی شد که نقاشی فریم بعدی را به تاخیر انداخت؟"
جدول زیر برخی از دادههای انتساب اولیه را که میتوانید از کتابخانه دریافت کنید نشان میدهد که میتواند به شما کمک کند برخی از دلایل سطح بالا تعاملات کند در وبسایت خود را کشف کنید:
کلید شی attribution | داده ها |
---|---|
interactionTarget | یک انتخابگر CSS که به عنصری اشاره میکند که مقدار INP صفحه را تولید میکند - برای مثال، button#save . |
interactionType | نوع تعامل، از کلیک، ضربه زدن، یا ورودی های صفحه کلید. |
inputDelay * | تأخیر ورودی تعامل |
processingDuration * | زمانی که اولین شنونده رویداد در پاسخ به تعامل کاربر شروع به اجرا کرد تا زمانی که پردازش شنونده رویداد به پایان رسید. |
presentationDelay * | تأخیر ارائه تعامل، که از زمانی که کنترل کننده رویداد به پایان می رسد تا زمانی که فریم بعدی نقاشی می شود، انجام می شود. |
longAnimationFrameEntries * | ورودیهای LoAF مرتبط با تعامل. برای اطلاعات بیشتر به ادامه مطلب مراجعه کنید |
با شروع نسخه 4 کتابخانه web-vitals، میتوانید از طریق دادههایی که با تفکیکهای فاز INP (تأخیر ورودی، مدت زمان پردازش و تأخیر ارائه) و Long Animation Frames API (LoAF) ارائه میکند، بینش عمیقتری در مورد تعاملات مشکلساز دریافت کنید.
The Long Animation Frames API (LoAF)
اشکال زدایی تعاملات با استفاده از داده های میدانی یک کار چالش برانگیز است. با این حال، با دادههای LoAF، اکنون میتوان بینشهای بهتری در مورد علل ایجاد تعاملات آهسته به دست آورد، زیرا LoAF تعدادی زمانبندی دقیق و سایر دادهها را نشان میدهد که میتوانید برای مشخص کردن دلایل دقیق استفاده کنید – و مهمتر از آن، جایی که منبع مشکل در کد وبسایت شما است.
ساخت اسناد کتابخانه web-vitals آرایهای از ورودیهای LoAF را در زیر کلید longAnimationFrameEntries
شی attribution
نشان میدهد. جدول زیر چند بیت کلیدی از دادههایی را که میتوانید در هر ورودی LoAF پیدا کنید فهرست میکند:
کلید شی ورودی LoAF | داده ها |
---|---|
duration | مدت زمان فریم طولانی انیمیشن، تا زمانی که چیدمان به پایان رسیده است، اما به استثنای نقاشی و ترکیب بندی. |
blockingDuration | کل مدت زمانی در فریم که مرورگر به دلیل کارهای طولانی قادر به پاسخگویی سریع نیست. این زمان مسدود کردن می تواند شامل کارهای طولانی در حال اجرا جاوا اسکریپت و همچنین هر کار رندر طولانی بعدی در فریم باشد. |
firstUIEventTimestamp | مهر زمانی زمانی که رویداد در طول فریم در صف قرار گرفت. برای پی بردن به شروع تاخیر ورودی یک تعامل مفید است. |
startTime | مهر زمانی شروع قاب. |
renderStart | زمانی که کار رندر قاب شروع شد. این شامل هر درخواست پاسخگویی به requestAnimationFrame (و پاسخهای تماس ResizeObserver در صورت وجود) میشود، اما احتمالاً قبل از شروع کار سبک/طرحبندی. |
styleAndLayoutStart | هنگامی که کار سبک / چیدمان در کادر اتفاق می افتد. می تواند در تعیین طول کار سبک/طرح بندی هنگام تعیین سایر مهرهای زمانی موجود مفید باشد. |
scripts | آرایه ای از موارد حاوی اطلاعات انتساب اسکریپت که به INP صفحه کمک می کند. |

blockingDuration
). همه این اطلاعات می توانند چیزهای زیادی را در مورد اینکه چه چیزی باعث کندی تعامل می شود به شما بگوید - اما آرایه scripts
که LoAF ورودی های سطح آن را نشان می دهد باید از جذابیت خاصی برخوردار باشد:
کلید شی انتساب اسکریپت | داده ها |
---|---|
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 | نام تابع در اسکریپت شناسایی شده. |
هر ورودی در این آرایه حاوی دادههای نشاندادهشده در این جدول است، که اطلاعاتی درباره اسکریپتی که مسئول تعامل آهسته بوده است - و نحوه انجام آن به شما میدهد.
اندازه گیری و شناسایی علل مشترک در پشت تعاملات کند
برای اینکه ایدهای در مورد نحوه استفاده از این اطلاعات به شما ارائه دهد، این راهنما اکنون نحوه استفاده از دادههای LoAF را که در کتابخانه web-vitals
ظاهر میشود برای تعیین برخی از دلایل پشت تعاملات آهسته توضیح میدهد.
مدت زمان پردازش طولانی
مدت زمان پردازش یک تعامل، زمانی است که طول می کشد تا فراخوان های کنترل کننده رویداد ثبت شده تعامل تا تکمیل شوند و هر چیز دیگری که ممکن است بین آنها اتفاق بیفتد. مدت زمان پردازش بالا توسط کتابخانه 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 ناشی می شود. می توانید مدت زمان این کار را با زمان بندی های LoAF که در کتابخانه web-vitals ظاهر می شود اندازه گیری کنید:
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
انجام میدهید، میتوانید از دادههای LoAF که توسط کتابخانه web-vitals ظاهر میشود برای شناسایی این سناریوها استفاده کنید:
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)، میتوانید در مورد اینکه کدام تعامل مشکلسازتر است، اطمینان بیشتری داشته باشید و سپس به تولید مجدد تعاملات مشکلدار در آزمایشگاه بروید و سپس به رفع آنها بپردازید.
تصویر قهرمان از Unsplash , توسط فدریکو رسپینی .
،بیاموزید که چگونه تعاملات آهسته را در داده های میدانی وب سایت خود پیدا کنید تا بتوانید فرصت هایی برای بهبود تعامل آن در Next Paint پیدا کنید.
دادههای میدانی دادههایی هستند که به شما میگویند کاربران واقعی وبسایت شما را چگونه تجربه میکنند. مشکلاتی را که نمی توانید به تنهایی در داده های آزمایشگاهی پیدا کنید، حل می کند. در مورد Interaction to Next Paint (INP) ، دادههای میدانی برای شناسایی تعاملات آهسته ضروری است و سرنخهای حیاتی برای کمک به رفع آنها ارائه میدهد.
در این راهنما، یاد خواهید گرفت که چگونه به سرعت INP وب سایت خود را با استفاده از داده های میدانی گزارش تجربه کاربر Chrome (CrUX) ارزیابی کنید تا ببینید آیا وب سایت شما با INP مشکل دارد یا خیر. متعاقباً، یاد خواهید گرفت که چگونه از ساخت اسناد کتابخانه جاوا اسکریپت web-vitals - و بینشهای جدیدی که از Long Animation Frames API (LoAF) ارائه میکند - برای جمعآوری و تفسیر دادههای میدانی برای تعاملات آهسته در وبسایت خود استفاده کنید.
برای ارزیابی INP وب سایت خود با CrUX شروع کنید
اگر اطلاعات میدانی را از کاربران وب سایت خود جمع آوری نمی کنید، CrUX ممکن است نقطه شروع خوبی باشد. CrUX داده های میدانی را از کاربران واقعی Chrome که ارسال داده های تله متری را انتخاب کرده اند جمع آوری می کند.
دادههای CrUX در تعدادی از مناطق مختلف ظاهر میشوند و این بستگی به دامنه اطلاعاتی دارد که به دنبال آن هستید. CrUX می تواند داده هایی را در مورد INP و دیگر Core Web Vitals برای موارد زیر ارائه دهد:
- صفحات منفرد و کل مبدا با استفاده از PageSpeed Insights .
- انواع صفحات. برای مثال، بسیاری از وبسایتهای تجارت الکترونیک دارای انواع صفحه جزئیات محصول و صفحه فهرست محصول هستند. میتوانید دادههای CrUX را برای انواع صفحات منحصربهفرد در کنسول جستجو دریافت کنید.
به عنوان نقطه شروع، می توانید URL وب سایت خود را در PageSpeed Insights وارد کنید. هنگامی که URL را وارد کردید، داده های فیلد مربوط به آن - در صورت وجود - برای چندین معیار از جمله INP نمایش داده می شود. همچنین می توانید از ضامن ها برای بررسی مقادیر INP خود برای ابعاد موبایل و دسکتاپ استفاده کنید.

این داده مفید است زیرا به شما می گوید که آیا مشکلی دارید. با این حال، کاری که CrUX نمی تواند انجام دهد این است که به شما بگوید چه چیزی باعث مشکلات می شود. راه حل های بسیاری برای نظارت بر کاربر واقعی (RUM) موجود است که به شما کمک می کند داده های میدانی خود را از کاربران وب سایت خود جمع آوری کنید تا به شما در پاسخ به آن کمک کند، و یک گزینه این است که خودتان آن داده های میدانی را با استفاده از کتابخانه JavaScript web-vitals جمع آوری کنید.
داده های میدانی را با کتابخانه جاوا اسکریپت web-vitals
جمع آوری کنید
کتابخانه جاوا اسکریپت web-vitals
یک اسکریپت است که می توانید برای جمع آوری داده های میدانی از کاربران وب سایت خود در وب سایت خود بارگذاری کنید. می توانید از آن برای ثبت تعدادی معیار از جمله INP در مرورگرهایی که از آن پشتیبانی می کنند استفاده کنید.
ساخت استاندارد کتابخانه web-vitals می تواند برای دریافت داده های اولیه INP از کاربران در این زمینه استفاده شود:
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 بیشتر بروید
ساختار اسناد کتابخانه web-vitals دادههای بیشتری را نشان میدهد که میتوانید از کاربران در این زمینه دریافت کنید تا به شما در عیبیابی بهتر تعاملات مشکلساز که بر INP وبسایت شما تأثیر میگذارند کمک کند. این داده ها از طریق شی attribution
ظاهر شده در روش onINP()
کتابخانه قابل دسترسی است:
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
});

علاوه بر خود INP صفحه، ساخت انتساب دادههای زیادی را ارائه میکند که میتوانید از آنها برای درک دلایل کندی تعامل استفاده کنید، از جمله اینکه باید روی کدام بخش از تعامل تمرکز کنید. می تواند به شما کمک کند به سوالات مهمی مانند:
- "آیا کاربر هنگام بارگیری صفحه با آن ارتباط برقرار کرده است؟"
- "آیا کنترل کننده های رویداد تعامل برای مدت طولانی اجرا می شدند؟"
- "آیا کد کنترل کننده رویداد تعامل با تاخیر شروع شده بود؟ اگر چنین است، در آن زمان چه چیز دیگری در رشته اصلی اتفاق می افتاد؟"
- "آیا این تعامل باعث رندر کار زیادی شد که نقاشی فریم بعدی را به تاخیر انداخت؟"
جدول زیر برخی از دادههای انتساب اولیه را که میتوانید از کتابخانه دریافت کنید نشان میدهد که میتواند به شما کمک کند برخی از دلایل سطح بالا تعاملات کند در وبسایت خود را کشف کنید:
کلید شی attribution | داده ها |
---|---|
interactionTarget | یک انتخابگر CSS که به عنصری اشاره میکند که مقدار INP صفحه را تولید میکند - برای مثال، button#save . |
interactionType | نوع تعامل، از کلیک، ضربه زدن، یا ورودی های صفحه کلید. |
inputDelay * | تاخیر ورودی تعامل |
processingDuration * | زمانی که اولین شنونده رویداد در پاسخ به تعامل کاربر شروع به اجرا کرد تا زمانی که پردازش شنونده رویداد به پایان رسید. |
presentationDelay * | تأخیر ارائه تعامل، که از زمانی که کنترل کننده رویداد به پایان می رسد تا زمانی که فریم بعدی نقاشی می شود، انجام می شود. |
longAnimationFrameEntries * | ورودیهای LoAF مرتبط با تعامل. برای اطلاعات بیشتر به ادامه مطلب مراجعه کنید |
با شروع نسخه 4 کتابخانه web-vitals، میتوانید از طریق دادههایی که با تفکیکهای فاز INP (تأخیر ورودی، مدت زمان پردازش و تأخیر ارائه) و Long Animation Frames API (LoAF) ارائه میکند، بینش عمیقتری در مورد تعاملات مشکلساز دریافت کنید.
The Long Animation Frames API (LoAF)
اشکال زدایی تعاملات با استفاده از داده های میدانی یک کار چالش برانگیز است. با این حال، با دادههای LoAF، اکنون میتوان بینشهای بهتری در مورد علل ایجاد تعاملات آهسته به دست آورد، زیرا LoAF تعدادی زمانبندی دقیق و سایر دادهها را نشان میدهد که میتوانید برای مشخص کردن دلایل دقیق استفاده کنید – و مهمتر از آن، جایی که منبع مشکل در کد وبسایت شما است.
ساخت اسناد کتابخانه web-vitals آرایهای از ورودیهای LoAF را در زیر کلید longAnimationFrameEntries
شی attribution
نشان میدهد. جدول زیر چند بیت کلیدی از دادههایی را که میتوانید در هر ورودی LoAF پیدا کنید فهرست میکند:
کلید شی ورودی LoAF | داده ها |
---|---|
duration | مدت زمان فریم طولانی انیمیشن، تا زمانی که چیدمان به پایان رسیده است، اما به استثنای نقاشی و ترکیب بندی. |
blockingDuration | کل مدت زمانی در فریم که مرورگر به دلیل کارهای طولانی قادر به پاسخگویی سریع نیست. این زمان مسدود کردن می تواند شامل کارهای طولانی در حال اجرا جاوا اسکریپت و همچنین هر کار رندر طولانی بعدی در فریم باشد. |
firstUIEventTimestamp | مهر زمانی زمانی که رویداد در طول فریم در صف قرار گرفت. برای پی بردن به شروع تاخیر ورودی یک تعامل مفید است. |
startTime | مهر زمانی شروع قاب. |
renderStart | زمانی که کار رندر قاب شروع شد. این شامل هر درخواست پاسخگویی به requestAnimationFrame (و پاسخهای تماس ResizeObserver در صورت وجود) میشود، اما احتمالاً قبل از شروع کار سبک/طرحبندی. |
styleAndLayoutStart | هنگامی که کار سبک / چیدمان در کادر اتفاق می افتد. می تواند در تعیین طول کار سبک/طرح بندی هنگام تعیین سایر مهرهای زمانی موجود مفید باشد. |
scripts | آرایه ای از موارد حاوی اطلاعات انتساب اسکریپت که به INP صفحه کمک می کند. |

blockingDuration
). همه این اطلاعات می توانند چیزهای زیادی را در مورد اینکه چه چیزی باعث کندی تعامل می شود به شما بگوید - اما آرایه scripts
که LoAF ورودی های سطح آن را نشان می دهد باید از جذابیت خاصی برخوردار باشد:
کلید شی انتساب اسکریپت | داده ها |
---|---|
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 | نام تابع در اسکریپت شناسایی شده. |
هر ورودی در این آرایه حاوی دادههای نشاندادهشده در این جدول است، که اطلاعاتی درباره اسکریپتی که مسئول تعامل آهسته بوده است - و نحوه انجام آن به شما میدهد.
اندازه گیری و شناسایی علل مشترک در پشت تعاملات کند
برای اینکه ایدهای در مورد نحوه استفاده از این اطلاعات به شما ارائه دهد، این راهنما اکنون نحوه استفاده از دادههای LoAF را که در کتابخانه web-vitals
ظاهر میشود برای تعیین برخی از دلایل پشت تعاملات آهسته توضیح میدهد.
مدت زمان پردازش طولانی
مدت زمان پردازش یک تعامل، زمانی است که طول می کشد تا فراخوان های کنترل کننده رویداد ثبت شده تعامل تا تکمیل شوند و هر چیز دیگری که ممکن است بین آنها اتفاق بیفتد. مدت زمان پردازش بالا توسط کتابخانه 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 ناشی می شود. می توانید مدت زمان این کار را با زمان بندی های LoAF که در کتابخانه web-vitals ظاهر می شود اندازه گیری کنید:
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 برای شناسایی این سناریوها ظاهر می شود ، استفاده کنید:
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 Web-Vitals (یا یک ارائه دهنده شایعه) ، می توانید اطمینان بیشتری داشته باشید که کدام تعامل بیشتر مشکل ساز است ، و سپس به تولید مثل تعامل مشکل ساز در آزمایشگاه بروید و سپس در مورد رفع آنها بروید.
تصویر قهرمان از Unsplash ، توسط فدریکو Respini .
،بیاموزید که چگونه تعامل آهسته را در داده های میدانی وب سایت خود پیدا کنید تا بتوانید فرصت هایی را برای بهبود تعامل آن با رنگ بعدی پیدا کنید.
داده های فیلد داده هایی است که به شما می گوید چگونه کاربران واقعی وب سایت شما را تجربه می کنند. این مواردی را که به تنهایی نمی توانید در داده های آزمایشگاهی پیدا کنید ، اذیت می کند. در مورد تعامل با رنگ بعدی (INP) ، داده های میدانی در شناسایی تعامل آهسته ضروری است و سرنخ های حیاتی را برای کمک به شما در رفع آنها فراهم می کند.
در این راهنما ، یاد می گیرید که چگونه می توانید INP وب سایت خود را با استفاده از داده های فیلد از گزارش تجربه کاربر Chrome (CRUX) ارزیابی کنید تا ببینید آیا وب سایت شما با INP مشکل دارد یا خیر. پس از آن ، شما یاد می گیرید که چگونه از انتساب کتابخانه Web-Vitals JavaScript استفاده کنید-و بینش های جدیدی که از قاب های انیمیشن طولانی API (LOAF) ارائه می دهد-برای جمع آوری و تفسیر داده های میدانی برای تعامل آهسته در وب سایت خود.
برای ارزیابی INP وب سایت خود با CRUX شروع کنید
اگر در حال جمع آوری داده های فیلد از کاربران وب سایت خود نیستید ، CRUX ممکن است نقطه شروع خوبی باشد. CRUX داده های میدانی را از کاربران واقعی Chrome که تصمیم به ارسال داده های تله متری گرفته اند ، جمع آوری می کند.
داده های CRUX در تعدادی از مناطق مختلف ظاهر می شود و به دامنه اطلاعات مورد نظر شما بستگی دارد. CRUX می تواند داده های مربوط به INP و سایر ویتام های اصلی وب را برای:
- صفحات جداگانه و کل منشأ با استفاده از بینش های pagespeed .
- انواع صفحات به عنوان مثال ، بسیاری از وب سایت های تجارت الکترونیک دارای صفحه جزئیات محصول و انواع صفحه لیست محصول هستند. می توانید داده های CRUX را برای انواع صفحه منحصر به فرد در کنسول جستجو دریافت کنید.
به عنوان یک نقطه شروع ، می توانید URL وب سایت خود را در Pagespeed Insights وارد کنید. پس از ورود به URL ، داده های فیلد برای آن - در صورت موجود بودن - برای چندین معیار از جمله INP نمایش داده می شود. همچنین می توانید از ضامن ها برای بررسی مقادیر INP خود برای ابعاد موبایل و دسک تاپ استفاده کنید.

این داده ها مفید است زیرا اگر مشکلی دارید به شما می گوید. با این حال ، کاری که Crux نمی تواند انجام دهد این است که به شما می گوید چه چیزی باعث ایجاد مشکل می شود. بسیاری از راه حل های واقعی نظارت بر کاربر (RUM) در دسترس است که به شما کمک می کند تا داده های فیلد خود را از کاربران وب سایت خود جمع آوری کنید تا به شما در پاسخ به این امر کمک کند ، و یک گزینه این است که خود را با استفاده از کتابخانه JavaScript Web-Vitals جمع کنید.
جمع آوری داده های فیلد با کتابخانه web-vitals
جاوا اسکریپت
کتابخانه JavaScript web-vitals
یک اسکریپت است که می توانید در وب سایت خود بارگیری کنید تا داده های فیلد را از کاربران وب سایت خود جمع آوری کنید. شما می توانید از آن برای ضبط تعدادی از معیارها ، از جمله INP در مرورگرهایی که از آن پشتیبانی می کنند استفاده کنید.
از ساخت استاندارد کتابخانه وب سایتها می توان برای دریافت داده های اساسی INP از کاربران در این زمینه استفاده کرد:
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 پیش بروید
انتساب ساخت کتابخانه های وب سایتهای داده های اضافی که می توانید از کاربران در این زمینه دریافت کنید تا به شما در عیب یابی بهتر تعاملات مشکل ساز که بر INP وب سایت شما تأثیر می گذارد ، کمک کند. این داده ها از طریق شیء attribution
که در روش onINP()
کتابخانه ظاهر می شود قابل دسترسی است:
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
});

علاوه بر خود INP صفحه ، ساخت انتساب داده های زیادی را که می توانید از آنها استفاده کنید برای کمک به درک دلایل تعامل آهسته ، از جمله بخشی از تعامل که باید روی آن تمرکز کنید ، فراهم می کند. این می تواند به شما در پاسخ به سؤالات مهم مانند:
- "آیا کاربر هنگام بارگیری با صفحه تعامل داشت؟"
- "آیا دستگیرندگان رویداد تعامل برای مدت طولانی اجرا شدند؟"
- "آیا کد کنترل کننده رویداد تعامل از شروع به تأخیر افتاد؟ اگر چنین است ، در آن زمان چه چیز دیگری روی موضوع اصلی اتفاق می افتد؟"
- "آیا تعامل باعث ایجاد کارهای ارائه شده زیادی شد که قاب بعدی را از رنگ آمیزی به تأخیر انداخت؟"
جدول زیر برخی از داده های اصلی انتساب را که می توانید از کتابخانه دریافت کنید نشان می دهد که می تواند به شما در تشخیص برخی از دلایل سطح بالا تعامل آهسته در وب سایت خود کمک کند:
کلید attribution | داده ها |
---|---|
interactionTarget | انتخاب کننده CSS به عنصری که مقدار INP صفحه را تولید می کند - برای مثال ، button#save . |
interactionType | نوع تعامل ، یا از ورودی ، شیر آب ، یا ورودی های صفحه کلید. |
inputDelay * | تأخیر ورودی تعامل. |
processingDuration * | زمان اولین شنونده رویداد در پاسخ به تعامل کاربر شروع به کار کرد تا زمانی که تمام پردازش شنوندگان رویداد به پایان رسید. |
presentationDelay * | تأخیر در ارائه تعامل ، که از زمانی که دستگیرندگان رویداد تا زمان نقاشی قاب بعدی به پایان می رسند ، اتفاق می افتد. |
longAnimationFrameEntries * | ورودی های مربوط به نان مرتبط با تعامل. برای اطلاعات بیشتر به بعدی مراجعه کنید. |
با شروع نسخه 4 کتابخانه وب ویتا ، می توانید از طریق داده هایی که با تجزیه فاز INP (تأخیر ورودی ، مدت زمان پردازش و تأخیر در ارائه ) ارائه می دهد ، بینش عمیق تری داشته باشید.
قاب های انیمیشن طولانی API (LOAF)
تعامل اشکال زدایی با استفاده از داده های میدانی یک کار چالش برانگیز است. با این وجود ، با توجه به داده های LOAF ، اکنون می توان بینش بهتری در مورد دلایل تعامل آهسته بدست آورد ، زیرا LOAF تعدادی از زمان بندی دقیق و سایر داده ها را که می توانید از آنها استفاده کنید ، برای مشخص کردن دلایل دقیق و مهمتر از همه ، جایی که منبع مشکل در کد وب سایت شما است ، قرار می دهد.
ساخت انتساب کتابخانه Web-Vitals مجموعه ای از ورودی های نان را در زیر کلید longAnimationFrameEntries
از شیء attribution
قرار می دهد. در جدول زیر چند بیت کلیدی از داده هایی که می توانید در هر ورودی نان پیدا کنید لیست شده است:
کلید شیء ورودی LOAF | داده ها |
---|---|
duration | مدت زمان قاب انیمیشن طولانی ، تا زمانی که طرح به پایان رسیده است ، اما به استثنای نقاشی و آهنگسازی. |
blockingDuration | کل زمان در قاب که مرورگر به دلیل کارهای طولانی قادر به پاسخ سریع نبود. این زمان مسدود کننده می تواند شامل کارهای طولانی در حال اجرا JavaScript و همچنین هر کار ارائه دهنده طولانی بعدی در قاب باشد. |
firstUIEventTimestamp | جدول زمانی زمانی که این رویداد در طول قاب صف می شد. برای فهمیدن شروع تأخیر ورودی یک تعامل مفید است. |
startTime | جدول زمانی شروع قاب. |
renderStart | هنگامی که کار رندر برای قاب آغاز شد. این شامل هر یک از تماس های requestAnimationFrame (و در صورت امکان پاسخ به تماس های ResizeObserver ) است ، اما به طور بالقوه قبل از شروع هر نوع کار سبک/چیدمان. |
styleAndLayoutStart | هنگامی که سبک/چیدمان در قاب کار می کند. می تواند در تشخیص طول کار سبک/چیدمان هنگام تشخیص در سایر زمان های موجود مفید باشد. |
scripts | مجموعه ای از موارد حاوی اطلاعات مربوط به انتساب اسکریپت که به INP صفحه کمک می کنند. |

blockingDuration
). همه این اطلاعات می تواند چیزهای زیادی در مورد چه چیزی باعث کند شدن تعامل می کند - اما آرایه scripts
که سطح ورودی های Loaf باید مورد توجه ویژه باشد:
کلید شیء انتساب اسکریپت | داده ها |
---|---|
invoker | Invoker این می تواند بر اساس نوع Invoker که در ردیف بعدی شرح داده شده متفاوت است. نمونه هایی از دعوت کنندگان می توانند مقادیری مانند 'IMG#id.onload' ، 'Window.requestAnimationFrame' یا 'Response.json.then' باشند. |
invokerType | نوع Invoker. می تواند 'user-callback' ، 'event-listener' ، 'resolve-promise' ، 'reject-promise' ، 'classic-script' یا 'module-script' باشد. |
sourceURL | URL به فیلمنامه ای که قاب انیمیشن طولانی از آن سرچشمه گرفته است. |
sourceCharPosition | موقعیت کاراکتر در فیلمنامه مشخص شده توسط sourceURL . |
sourceFunctionName | نام عملکرد در اسکریپت مشخص شده. |
هر ورودی در این آرایه شامل داده های نشان داده شده در این جدول است ، که اطلاعاتی در مورد اسکریپت که مسئول تعامل آهسته است - و نحوه مسئولیت آن به شما می دهد.
دلایل مشترک در تعامل آهسته را اندازه گیری و شناسایی کنید
برای اینکه ایده ای در مورد چگونگی استفاده از این اطلاعات به شما ارائه دهید ، این راهنما اکنون چگونه می توانید از داده های نان در کتابخانه web-vitals
استفاده کنید تا برخی از دلایل تعامل آهسته را تعیین کنید.
مدت زمان پردازش طولانی
مدت زمان پردازش یک تعامل زمانی است که برای تماس با تماسهای کنترل کننده رویداد ثبت شده در تعامل انجام می شود تا به اتمام برسند و هر چیز دیگری که ممکن است بین آنها اتفاق بیفتد. مدت زمان پردازش زیاد توسط کتابخانه وب سایت ها ظاهر می شود:
import {onINP} from 'web-vitals/attribution';
onINP(({name, value, attribution}) => {
const {processingDuration} = attribution; // 512.5
});
طبیعی است که فکر کنیم علت اصلی تعامل آهسته این است که کد کنترل کننده رویداد شما خیلی طولانی طول کشید ، اما همیشه اینگونه نیست! هنگامی که تأیید کردید که این مشکل است ، می توانید با داده های نان عمیق تر حفر کنید:
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'
}
});
همانطور که در قطعه کد قبلی مشاهده می کنید ، می توانید با داده های نان کار کنید تا علت دقیق تعامل با مقادیر طولانی مدت پردازش را ردیابی کنید ، از جمله:
- عنصر و شنونده رویداد ثبت شده آن.
- پرونده اسکریپت و موقعیت کاراکتر موجود در آن-حاوی کد کنترل کننده رویداد طولانی مدت است.
- نام عملکرد.
این نوع داده ها بسیار ارزشمند است. شما دیگر نیازی به انجام کار در پیدا کردن دقیقاً کدام تعامل - یا کدام یک از گیرنده های رویداد آن - مسئولیت مقادیر طولانی مدت پردازش را ندارید. همچنین ، از آنجا که اسکریپت های شخص ثالث اغلب می توانند دستگیرندگان رویداد خود را ثبت کنند ، می توانید تعیین کنید که آیا این کد شما مسئول بوده است یا نه! برای کدی که کنترل آن را دارید ، می خواهید به دنبال بهینه سازی کارهای طولانی باشید.
تأخیرهای ورودی طولانی
در حالی که دستگیرندگان رویداد طولانی مدت مشترک هستند ، بخش های دیگری از تعامل وجود دارد که باید در نظر بگیرند. یک قسمت قبل از مدت زمان پردازش رخ می دهد ، که به عنوان تأخیر ورودی شناخته می شود. این زمان از زمانی است که کاربر تعامل را آغاز می کند ، تا لحظه ای که تماس های تماس گیرنده رویداد آن شروع به کار می کند و هنگامی که موضوع اصلی در حال پردازش کار دیگری است ، اتفاق می افتد. ساخت انتساب کتابخانه وب ویتا می تواند طول تأخیر ورودی را برای تعامل به شما بگوید:
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'
}
});
همانطور که در مورد عیب یابی مقادیر طولانی مدت پردازش وجود دارد ، تأخیرهای ورودی بالا به دلایل ذکر شده در ابتدا داده های مربوط به انتساب اسکریپت را به شما می دهد. با این حال ، آنچه متفاوت است این است که نوع Invoker بر اساس ماهیت کارهایی که تعامل را به تأخیر می اندازد تغییر خواهد کرد:
-
'user-callback'
نشان می دهد که کار مسدود کردن ازsetInterval
،setTimeout
یا حتیrequestAnimationFrame
بوده است. -
'event-listener'
نشان می دهد که کار مسدود کننده از ورودی قبلی بود که صف شده بود و هنوز پردازش می شد. -
'resolve-promise'
و'reject-promise'
به این معنی است که کار مسدود کننده از برخی از کارهای ناهمزمان بود که زودتر شروع شد و در زمانی که کاربر سعی در تعامل با صفحه داشت ، حل یا رد شد.
در هر صورت ، داده های انتساب اسکریپت به شما این حس را می دهد که از کجا شروع به جستجو کنید ، و اینکه آیا تأخیر ورودی به دلیل کد شخصی شما یا یک اسکریپت شخص ثالث بوده است.
تأخیر در ارائه طولانی
تأخیرهای ارائه آخرین مایل تعامل است و از زمان پایان کارگران رویداد تعامل ، تا جایی که قاب بعدی نقاشی شده است ، شروع می شود. آنها هنگامی اتفاق می افتند که کار در یک کنترل کننده رویداد به دلیل تعامل ، وضعیت بصری رابط کاربری را تغییر می دهد. همانطور که با مدت زمان پردازش و تأخیرهای ورودی ، کتابخانه وب سایت می تواند به شما بگوید تاخیر ارائه برای تعامل چقدر بوده است:
import {onINP} from 'web-vitals/attribution';
onINP(({name, value, attribution}) => {
const {presentationDelay} = attribution; // 113.32307691
});
اگر این داده ها را ضبط کرده و تأخیرهای ارائه شده برای تعامل در INP وب سایت خود را مشاهده می کنید ، مقصر می تواند متفاوت باشد ، اما در اینجا یک زن و شوهر وجود دارد که باعث می شوند در جستجوی آنها باشند.
سبک گران قیمت و کار چیدمان
تأخیر در ارائه طولانی ممکن است محاسبه مجدد به سبک و کار طرح بندی باشد که از دلایل مختلفی ناشی می شود ، از جمله انتخاب کنندگان پیچیده CSS و اندازه های بزرگ . شما می توانید مدت زمان این کار را با زمان بندی نان که در کتابخانه وب سایتها ظاهر می شود ، اندازه گیری کنید:
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 برای شناسایی این سناریوها ظاهر می شود ، استفاده کنید:
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 Web-Vitals (یا یک ارائه دهنده شایعه) ، می توانید اطمینان بیشتری داشته باشید که کدام تعامل بیشتر مشکل ساز است ، و سپس به تولید مثل تعامل مشکل ساز در آزمایشگاه بروید و سپس در مورد رفع آنها بروید.
تصویر قهرمان از Unsplash ، توسط فدریکو Respini .
،بیاموزید که چگونه تعامل آهسته را در داده های میدانی وب سایت خود پیدا کنید تا بتوانید فرصت هایی را برای بهبود تعامل آن با رنگ بعدی پیدا کنید.
داده های فیلد داده هایی است که به شما می گوید چگونه کاربران واقعی وب سایت شما را تجربه می کنند. این مواردی را که به تنهایی نمی توانید در داده های آزمایشگاهی پیدا کنید ، اذیت می کند. در مورد تعامل با رنگ بعدی (INP) ، داده های میدانی در شناسایی تعامل آهسته ضروری است و سرنخ های حیاتی را برای کمک به شما در رفع آنها فراهم می کند.
در این راهنما ، یاد می گیرید که چگونه می توانید INP وب سایت خود را با استفاده از داده های فیلد از گزارش تجربه کاربر Chrome (CRUX) ارزیابی کنید تا ببینید آیا وب سایت شما با INP مشکل دارد یا خیر. پس از آن ، شما یاد می گیرید که چگونه از انتساب کتابخانه Web-Vitals JavaScript استفاده کنید-و بینش های جدیدی که از قاب های انیمیشن طولانی API (LOAF) ارائه می دهد-برای جمع آوری و تفسیر داده های میدانی برای تعامل آهسته در وب سایت خود.
برای ارزیابی INP وب سایت خود با CRUX شروع کنید
اگر در حال جمع آوری داده های فیلد از کاربران وب سایت خود نیستید ، CRUX ممکن است نقطه شروع خوبی باشد. CRUX داده های میدانی را از کاربران واقعی Chrome که تصمیم به ارسال داده های تله متری گرفته اند ، جمع آوری می کند.
داده های CRUX در تعدادی از مناطق مختلف ظاهر می شود و به دامنه اطلاعات مورد نظر شما بستگی دارد. CRUX می تواند داده های مربوط به INP و سایر ویتام های اصلی وب را برای:
- صفحات جداگانه و کل منشأ با استفاده از بینش های pagespeed .
- انواع صفحات به عنوان مثال ، بسیاری از وب سایت های تجارت الکترونیک دارای صفحه جزئیات محصول و انواع صفحه لیست محصول هستند. می توانید داده های CRUX را برای انواع صفحه منحصر به فرد در کنسول جستجو دریافت کنید.
به عنوان یک نقطه شروع ، می توانید URL وب سایت خود را در Pagespeed Insights وارد کنید. پس از ورود به URL ، داده های فیلد برای آن - در صورت موجود بودن - برای چندین معیار از جمله INP نمایش داده می شود. همچنین می توانید از ضامن ها برای بررسی مقادیر INP خود برای ابعاد موبایل و دسک تاپ استفاده کنید.

این داده ها مفید است زیرا اگر مشکلی دارید به شما می گوید. با این حال ، کاری که Crux نمی تواند انجام دهد این است که به شما می گوید چه چیزی باعث ایجاد مشکل می شود. بسیاری از راه حل های واقعی نظارت بر کاربر (RUM) در دسترس است که به شما کمک می کند تا داده های فیلد خود را از کاربران وب سایت خود جمع آوری کنید تا به شما در پاسخ به این امر کمک کند ، و یک گزینه این است که خود را با استفاده از کتابخانه JavaScript Web-Vitals جمع کنید.
جمع آوری داده های فیلد با کتابخانه web-vitals
جاوا اسکریپت
کتابخانه JavaScript web-vitals
یک اسکریپت است که می توانید در وب سایت خود بارگیری کنید تا داده های فیلد را از کاربران وب سایت خود جمع آوری کنید. شما می توانید از آن برای ضبط تعدادی از معیارها ، از جمله INP در مرورگرهایی که از آن پشتیبانی می کنند استفاده کنید.
از ساخت استاندارد کتابخانه وب سایتها می توان برای دریافت داده های اساسی INP از کاربران در این زمینه استفاده کرد:
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 پیش بروید
انتساب ساخت کتابخانه های وب سایتهای داده های اضافی که می توانید از کاربران در این زمینه دریافت کنید تا به شما در عیب یابی بهتر تعاملات مشکل ساز که بر INP وب سایت شما تأثیر می گذارد ، کمک کند. این داده ها از طریق شیء attribution
که در روش onINP()
کتابخانه ظاهر می شود قابل دسترسی است:
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
});

علاوه بر خود INP صفحه ، ساخت انتساب داده های زیادی را که می توانید از آنها استفاده کنید برای کمک به درک دلایل تعامل آهسته ، از جمله بخشی از تعامل که باید روی آن تمرکز کنید ، فراهم می کند. این می تواند به شما در پاسخ به سؤالات مهم مانند:
- "آیا کاربر هنگام بارگیری با صفحه تعامل داشت؟"
- "آیا دستگیرندگان رویداد تعامل برای مدت طولانی اجرا شدند؟"
- "آیا کد کنترل کننده رویداد تعامل از شروع به تأخیر افتاد؟ اگر چنین است ، در آن زمان چه چیز دیگری روی موضوع اصلی اتفاق می افتد؟"
- "آیا تعامل باعث ایجاد کارهای ارائه شده زیادی شد که قاب بعدی را از رنگ آمیزی به تأخیر انداخت؟"
جدول زیر برخی از داده های اصلی انتساب را که می توانید از کتابخانه دریافت کنید نشان می دهد که می تواند به شما در تشخیص برخی از دلایل سطح بالا تعامل آهسته در وب سایت خود کمک کند:
کلید attribution | داده ها |
---|---|
interactionTarget | انتخاب کننده CSS به عنصری که مقدار INP صفحه را تولید می کند - برای مثال ، button#save . |
interactionType | نوع تعامل ، یا از ورودی ، شیر آب ، یا ورودی های صفحه کلید. |
inputDelay * | تأخیر ورودی تعامل. |
processingDuration * | زمان اولین شنونده رویداد در پاسخ به تعامل کاربر شروع به کار کرد تا زمانی که تمام پردازش شنوندگان رویداد به پایان رسید. |
presentationDelay * | تأخیر در ارائه تعامل ، که از زمانی که دستگیرندگان رویداد تا زمان نقاشی قاب بعدی به پایان می رسند ، اتفاق می افتد. |
longAnimationFrameEntries * | ورودی های مربوط به نان مرتبط با تعامل. برای اطلاعات بیشتر به بعدی مراجعه کنید. |
با شروع نسخه 4 کتابخانه وب ویتا ، می توانید از طریق داده هایی که با تجزیه فاز INP (تأخیر ورودی ، مدت زمان پردازش و تأخیر در ارائه ) ارائه می دهد ، بینش عمیق تری داشته باشید.
قاب های انیمیشن طولانی API (LOAF)
تعامل اشکال زدایی با استفاده از داده های میدانی یک کار چالش برانگیز است. با این وجود ، با توجه به داده های LOAF ، اکنون می توان بینش بهتری در مورد دلایل تعامل آهسته بدست آورد ، زیرا LOAF تعدادی از زمان بندی دقیق و سایر داده ها را که می توانید از آنها استفاده کنید ، برای مشخص کردن دلایل دقیق و مهمتر از همه ، جایی که منبع مشکل در کد وب سایت شما است ، قرار می دهد.
ساخت انتساب کتابخانه Web-Vitals مجموعه ای از ورودی های نان را در زیر کلید longAnimationFrameEntries
از شیء attribution
قرار می دهد. در جدول زیر چند بیت کلیدی از داده هایی که می توانید در هر ورودی نان پیدا کنید لیست شده است:
کلید شیء ورودی LOAF | داده ها |
---|---|
duration | مدت زمان قاب انیمیشن طولانی ، تا زمانی که طرح به پایان رسیده است ، اما به استثنای نقاشی و آهنگسازی. |
blockingDuration | کل زمان در قاب که مرورگر به دلیل کارهای طولانی قادر به پاسخ سریع نبود. این زمان مسدود کننده می تواند شامل کارهای طولانی در حال اجرا JavaScript و همچنین هر کار ارائه دهنده طولانی بعدی در قاب باشد. |
firstUIEventTimestamp | جدول زمانی زمانی که این رویداد در طول قاب صف می شد. برای فهمیدن شروع تأخیر ورودی یک تعامل مفید است. |
startTime | جدول زمانی شروع قاب. |
renderStart | هنگامی که کار رندر برای قاب آغاز شد. این شامل هر یک از تماس های requestAnimationFrame (و در صورت امکان پاسخ به تماس های ResizeObserver ) است ، اما به طور بالقوه قبل از شروع هر نوع کار سبک/چیدمان. |
styleAndLayoutStart | هنگامی که سبک/چیدمان در قاب کار می کند. می تواند در تشخیص طول کار سبک/چیدمان هنگام تشخیص در سایر زمان های موجود مفید باشد. |
scripts | مجموعه ای از موارد حاوی اطلاعات مربوط به انتساب اسکریپت که به INP صفحه کمک می کنند. |

blockingDuration
). همه این اطلاعات می تواند چیزهای زیادی در مورد چه چیزی باعث کند شدن تعامل می کند - اما آرایه scripts
که سطح ورودی های Loaf باید مورد توجه ویژه باشد:
کلید شیء انتساب اسکریپت | داده ها |
---|---|
invoker | Invoker این می تواند بر اساس نوع Invoker که در ردیف بعدی شرح داده شده متفاوت است. نمونه هایی از دعوت کنندگان می توانند مقادیری مانند 'IMG#id.onload' ، 'Window.requestAnimationFrame' یا 'Response.json.then' باشند. |
invokerType | نوع Invoker. می تواند 'user-callback' ، 'event-listener' ، 'resolve-promise' ، 'reject-promise' ، 'classic-script' یا 'module-script' باشد. |
sourceURL | URL به فیلمنامه ای که قاب انیمیشن طولانی از آن سرچشمه گرفته است. |
sourceCharPosition | موقعیت کاراکتر در فیلمنامه مشخص شده توسط sourceURL . |
sourceFunctionName | نام عملکرد در اسکریپت مشخص شده. |
هر ورودی در این آرایه شامل داده های نشان داده شده در این جدول است ، که اطلاعاتی در مورد اسکریپت که مسئول تعامل آهسته است - و نحوه مسئولیت آن به شما می دهد.
دلایل مشترک در تعامل آهسته را اندازه گیری و شناسایی کنید
برای اینکه ایده ای در مورد چگونگی استفاده از این اطلاعات به شما ارائه دهید ، این راهنما اکنون چگونه می توانید از داده های نان در کتابخانه web-vitals
استفاده کنید تا برخی از دلایل تعامل آهسته را تعیین کنید.
مدت زمان پردازش طولانی
مدت زمان پردازش یک تعامل زمانی است که برای تماس با تماسهای کنترل کننده رویداد ثبت شده در تعامل انجام می شود تا به اتمام برسند و هر چیز دیگری که ممکن است بین آنها اتفاق بیفتد. مدت زمان پردازش زیاد توسط کتابخانه وب سایت ها ظاهر می شود:
import {onINP} from 'web-vitals/attribution';
onINP(({name, value, attribution}) => {
const {processingDuration} = attribution; // 512.5
});
طبیعی است که فکر کنیم علت اصلی تعامل آهسته این است که کد کنترل کننده رویداد شما خیلی طولانی طول کشید ، اما همیشه اینگونه نیست! هنگامی که تأیید کردید که این مشکل است ، می توانید با داده های نان عمیق تر حفر کنید:
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'
}
});
همانطور که در قطعه کد قبلی مشاهده می کنید ، می توانید با داده های نان کار کنید تا علت دقیق تعامل با مقادیر طولانی مدت پردازش را ردیابی کنید ، از جمله:
- عنصر و شنونده رویداد ثبت شده آن.
- پرونده اسکریپت و موقعیت کاراکتر موجود در آن-حاوی کد کنترل کننده رویداد طولانی مدت است.
- نام عملکرد.
این نوع داده ها بسیار ارزشمند است. شما دیگر نیازی به انجام کار در پیدا کردن دقیقاً کدام تعامل - یا کدام یک از گیرنده های رویداد آن - مسئولیت مقادیر طولانی مدت پردازش را ندارید. همچنین ، از آنجا که اسکریپت های شخص ثالث اغلب می توانند دستگیرندگان رویداد خود را ثبت کنند ، می توانید تعیین کنید که آیا این کد شما مسئول بوده است یا نه! برای کدی که کنترل آن را دارید ، می خواهید به دنبال بهینه سازی کارهای طولانی باشید.
تأخیرهای ورودی طولانی
در حالی که دستگیرندگان رویداد طولانی مدت مشترک هستند ، بخش های دیگری از تعامل وجود دارد که باید در نظر بگیرند. یک قسمت قبل از مدت زمان پردازش رخ می دهد ، که به عنوان تأخیر ورودی شناخته می شود. این زمان از زمانی است که کاربر تعامل را آغاز می کند ، تا لحظه ای که تماس های تماس گیرنده رویداد آن شروع به کار می کند و هنگامی که موضوع اصلی در حال پردازش کار دیگری است ، اتفاق می افتد. ساخت انتساب کتابخانه وب ویتا می تواند طول تأخیر ورودی را برای تعامل به شما بگوید:
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'
}
});
As is the case with troubleshooting high processing duration values, high input delays due to the causes mentioned earlier will give you detailed script attribution data. What is different, however, is that the invoker type will change based on the nature of the work that delayed the interaction:
-
'user-callback'
indicates the blocking task was fromsetInterval
,setTimeout
, or evenrequestAnimationFrame
. -
'event-listener'
indicates that the blocking task was from an earlier input that was queued and still processing. -
'resolve-promise'
and'reject-promise'
means that the blocking task was from some asynchronous work that was kicked off earlier, and resolved or rejected at a time when the user attempted to interact with the page, delaying the interaction.
In any case, the script attribution data will give you a sense of where to start looking, and whether the input delay was due to your own code, or that of a third-party script.
Long presentation delays
Presentation delays are the last mile of an interaction, and begin when the interaction's event handlers finish, up to the point at which the next frame was painted. They occur when the work in an event handler due to an interaction changes the visual state of the user interface. As with processing durations and input delays, the web-vitals library can tell you how long the presentation delay was for an interaction:
import {onINP} from 'web-vitals/attribution';
onINP(({name, value, attribution}) => {
const {presentationDelay} = attribution; // 113.32307691
});
If you record this data and see high presentation delays for interactions contributing to your website's INP, the culprits can vary, but here are a couple causes to be on the lookout for.
Expensive style and layout work
Long presentation delays may be expensive style recalculation and layout work that arises from a number of causes, including complex CSS selectors and large DOM sizes . You can measure the duration this work with the LoAF timings surfaced in the web-vitals library:
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 won't tell you the duration of the style and layout work is for a frame, but it will tell you when it started. With this starting timestamp, you can use other data from LoAF to calculate an accurate duration of that work by determining the end time of the frame, and subtracting the start timestamp of the style and layout work from that.
Long-running requestAnimationFrame
callbacks
One potential cause of long presentation delays is excessive work done in a requestAnimationFrame
callback. The contents of this callback are executed after event handlers have finished running, but just prior to style recalculation and layout work.
These callbacks can take considerable time to complete if the work done within them is complex. If you suspect high presentation delay values are due to work you're doing with requestAnimationFrame
, you can use LoAF data surfaced by the web-vitals library to identify these scenarios:
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'
}
});
If you see that a significant portion of the presentation delay time is spent in a requestAnimationFrame
callback, ensure the work you're doing in these callbacks is limited to performing work that results in an actual update to the user interface. Any other work that doesn't touch the DOM or update styles will unnecessarily delay the next frame from being painted, so be careful!
نتیجه گیری
Field data is the best source of information you can draw on when it comes to understanding which interactions are problematic for actual users in the field. By relying on field data collection tools such as the web-vitals JavaScript library (or a RUM provider), you can be more confident about which interactions are most problematic, and then move on to reproducing problematic interactions in the lab and then go about fixing them.
Hero image from Unsplash , by Federico Respini .