Long Animation Frames API (با تلفظ LoAF Lo-Af) بهروزرسانی Long Tasks API است تا درک بهتری از بهروزرسانیهای رابط کاربر آهسته (UI) ارائه دهد. این میتواند برای شناسایی فریمهای پویانمایی آهسته که احتمالاً بر معیار Interaction to Next Paint (INP) Core Web Vital که میزان پاسخدهی را اندازهگیری میکند، تأثیر میگذارد، یا برای شناسایی سایر جابهجاییهای رابط کاربری که بر صافی تأثیر میگذارند، مفید باشد.
وضعیت API
پس از آزمایش اولیه از Chrome 116 به Chrome 122 ، LoAF API از Chrome 123 ارسال شد.
پس زمینه: Long Tasks API
Long Animation Frames API جایگزینی برای Long Tasks API است که مدتی است (از Chrome 58) در Chrome موجود است. همانطور که از نامش پیداست، Long Task API به شما امکان می دهد کارهای طولانی را نظارت کنید، کارهایی که رشته اصلی را برای 50 میلی ثانیه یا بیشتر اشغال می کنند. کارهای طولانی را می توان با استفاده از رابط PerformanceLongTaskTiming
، با PeformanceObserver
مانیتور کرد:
const observer = new PerformanceObserver((list) => {
console.log(list.getEntries());
});
observer.observe({ type: 'longtask', buffered: true });
کارهای طولانی احتمالا باعث مشکلات پاسخگویی می شوند. اگر کاربر سعی کند با یک صفحه تعامل داشته باشد - به عنوان مثال، روی یک دکمه کلیک کند یا یک منو باز کند - اما موضوع اصلی در حال حاضر با یک کار طولانی سروکار دارد، در این صورت تعامل کاربر در انتظار تکمیل آن کار به تاخیر می افتد .
برای بهبود پاسخگویی، اغلب توصیه می شود کارهای طولانی را از بین ببرید . اگر هر کار طولانی به جای آن به مجموعه ای از وظایف متعدد و کوچکتر تقسیم شود، ممکن است اجازه دهد تا وظایف مهم تری در بین آنها اجرا شود تا از تأخیر قابل توجه در پاسخگویی به تعاملات جلوگیری شود.
بنابراین هنگام تلاش برای بهبود پاسخگویی، اولین تلاش اغلب اجرای یک ردیابی عملکرد و بررسی وظایف طولانی است. این میتواند از طریق یک ابزار ممیزی مبتنی بر آزمایشگاه مانند Lighthouse (که دارای ممیزی از کارهای طولانی رشته اصلی اجتناب شود )، یا با مشاهده کارهای طولانی در ابزار توسعه کروم باشد.
آزمایش مبتنی بر آزمایشگاه اغلب محل شروع ضعیفی برای شناسایی مسائل مربوط به پاسخگویی است، زیرا این ابزارها ممکن است شامل تعاملات نباشند—در صورت وجود، زیرمجموعه کوچکی از تعاملات احتمالی هستند. در حالت ایدهآل، میتوانید دلایل کندی تعاملات را در این زمینه اندازهگیری کنید.
کاستی های Long Tasks API
اندازهگیری کارهای طولانی در میدان با استفاده از مشاهدهگر عملکرد فقط تا حدودی مفید است. در واقع، اطلاعات زیادی فراتر از این که یک کار طولانی اتفاق افتاده است، و اینکه چقدر طول کشیده است، نمی دهد.
ابزارهای نظارت بر کاربر واقعی (RUM) اغلب از این برای افزایش تعداد یا مدت کارهای طولانی یا شناسایی صفحاتی که در آنها انجام میشوند استفاده میکنند - اما بدون جزئیات اساسی در مورد علت انجام کار طولانی، این فقط کاربرد محدودی دارد. Long Tasks API فقط یک مدل انتساب اولیه دارد، که در بهترین حالت فقط به شما میگوید ظرفی که وظیفه طولانی در آن اتفاق افتاده است (سند سطح بالا یا یک <iframe>
)، اما نه اسکریپت یا تابعی که آن را فراخوانی کرده است، همانطور که نشان داده شده است یک ورودی معمولی:
{
"name": "unknown",
"entryType": "longtask",
"startTime": 31.799999997019768,
"duration": 136,
"attribution": [
{
"name": "unknown",
"entryType": "taskattribution",
"startTime": 0,
"duration": 0,
"containerType": "window",
"containerSrc": "",
"containerId": "",
"containerName": ""
}
]
}
Long Tasks API نیز یک نمای ناقص است، زیرا ممکن است برخی از وظایف مهم را نیز حذف کند. برخی بهروزرسانیها - مانند رندر کردن - در وظایف جداگانهای اتفاق میافتند که در حالت ایدهآل باید همراه با اجرای قبلی گنجانده شوند که باعث شد آن بهروزرسانی بهدقت «کل کار» آن تعامل را اندازهگیری کند. برای جزئیات بیشتر در مورد محدودیتهای تکیه بر وظایف، به بخش «جایی که کارهای طولانی کوتاه میآیند» توضیحدهنده مراجعه کنید.
مسئله نهایی این است که اندازه گیری کارهای طولانی فقط در مورد کارهای فردی گزارش می دهد که بیش از حد مجاز 50 میلی ثانیه طول می کشد. یک فریم انیمیشن میتواند از چندین کار کوچکتر از این محدودیت 50 میلیثانیهای تشکیل شود، اما در مجموع همچنان توانایی مرورگر را برای رندر کردن مسدود میکند.
Long Animation Frames API
Long Animation Frames API (LoAF) یک API جدید است که به دنبال رفع برخی از کاستیهای Long Tasks API است تا توسعهدهندگان را قادر میسازد تا بینشهای عملیتری برای کمک به رفع مشکلات پاسخگویی و بهبود INP و همچنین بهدست آوردن بینشهایی در مورد مسائل روانی به دست آورند. .
پاسخگویی خوب به این معنی است که یک صفحه به سرعت به تعاملات ایجاد شده با آن پاسخ می دهد. این شامل این می شود که بتوانید هر به روز رسانی مورد نیاز کاربر را به موقع رنگ آمیزی کنید و از مسدود کردن این به روز رسانی ها جلوگیری کنید. برای INP، توصیه می شود در 200 میلی ثانیه یا کمتر پاسخ دهید ، اما برای به روز رسانی های دیگر (مثلاً انیمیشن ها) حتی 200 میلی ثانیه ممکن است خیلی طولانی باشد.
Long Animation Frames API یک رویکرد جایگزین برای اندازهگیری کار مسدود کردن است. Long Animation Frames API به جای اندازهگیری تکالیف ، فریمهای طولانی انیمیشن را اندازهگیری میکند. فریم انیمیشن طولانی زمانی است که بهروزرسانی رندر بیش از 50 میلیثانیه به تأخیر بیفتد (همان آستانه برای Long Tasks API).
فریم های بلند انیمیشن از ابتدای کارهایی که نیاز به رندر دارند اندازه گیری می شوند. در جایی که اولین کار در یک فریم انیمیشن طولانی بالقوه نیازی به رندر ندارد، فریم انیمیشن طولانی پس از اتمام کار غیر رندر پایان مییابد و یک فریم انیمیشن طولانی بالقوه جدید با کار بعدی شروع میشود. چنین فریمهای انیمیشن طولانی بدون رندر هنوز در Long Animation Frames API زمانی که بیش از 50 میلیثانیه است (با زمان renderStart
0) گنجانده میشود تا امکان اندازهگیری کارهای مسدودکننده بالقوه را فراهم کند.
فریم های طولانی انیمیشن را می توان به روشی مشابه کارهای طولانی با PerformanceObserver
مشاهده کرد، اما در عوض به نوع long-animation-frame
نگاه کرد:
const observer = new PerformanceObserver((list) => {
console.log(list.getEntries());
});
observer.observe({ type: 'long-animation-frame', buffered: true });
فریم های انیمیشن طولانی قبلی را نیز می توان از جدول زمانی عملکرد جستجو کرد:
const loafs = performance.getEntriesByType('long-animation-frame');
با این حال، یک maxBufferSize
برای ورودی های عملکرد وجود دارد که پس از آن ورودی های جدیدتر حذف می شوند، بنابراین رویکرد PerformanceObserver رویکرد توصیه شده است. اندازه بافر long-animation-frame
روی 200 تنظیم شده است، مانند long-tasks
.
مزایای نگاه کردن به فریم ها به جای وظایف
مزیت اصلی نگاه کردن به این موضوع از منظر فریم و نه از منظر وظایف، این است که یک انیمیشن طولانی میتواند از هر تعداد کار تشکیل شود که در مجموع به یک فریم انیمیشن طولانی منجر شود. این به آخرین نکتهای که قبلاً اشاره شد، میپردازد، جایی که مجموع بسیاری از کارهای کوچکتر و مسدودکننده رندر قبل از یک فریم انیمیشن ممکن است توسط Long Tasks API ظاهر نشود.
مزیت دیگر این نمای جایگزین در کارهای طولانی، توانایی ارائه زمان بندی خرابی کل فریم است. LoAF به جای صرفاً شامل startTime
و duration
، مانند Long Tasks API، شامل تفکیک بسیار دقیق تری از بخش های مختلف مدت زمان فریم است.
مُهرهای زمانی فریم و مدت زمان
-
startTime
: زمان شروع قاب طولانی انیمیشن نسبت به زمان شروع ناوبری. -
duration
: مدت زمان فریم طولانی انیمیشن (بدون احتساب زمان ارائه). -
renderStart
: زمان شروع چرخه رندر، که شامل پاسخ تماسهایrequestAnimationFrame
، محاسبه سبک و طرحبندی، تغییر اندازه ناظر و تماسهای ناظر تقاطع است. -
styleAndLayoutStart
: آغاز دوره زمانی صرف شده در محاسبات سبک و چیدمان. -
firstUIEventTimestamp
: زمان اولین رویداد UI (ماوس/صفحه کلید و غیره) که در طول این فریم مدیریت می شود. -
blockingDuration
: کل مدت زمان بر حسب میلی ثانیه که فریم انیمیشن پردازش ورودی یا سایر وظایف با اولویت بالا را مسدود می کند.
توضیحی در مورد blockingDuration
یک فریم انیمیشن طولانی ممکن است از تعدادی کار تشکیل شده باشد. blockingDuration
مجموع مدت زمان کار بیشتر از 50 میلی ثانیه است (شامل مدت زمان رندر نهایی در طولانی ترین کار).
برای مثال، اگر یک فریم انیمیشن طولانی از دو کار 55 میلیثانیه و 65 میلیثانیه و به دنبال آن یک رندر 20 میلیثانیهای تشکیل شده باشد، آنگاه duration
تقریباً 140 میلیثانیه با مدت blockingDuration
(55 - 50) + (65 + 20) خواهد بود. - 50) = 40 میلی ثانیه. برای 40 میلی ثانیه در طول این فریم انیمیشن طولانی 140 میلی ثانیه، فریم از مدیریت ورودی مسدود شده در نظر گرفته شد.
چه به duration
نگاه کنیم یا blockingDuration
برای نمایشگر معمولی 60 هرتز، یک مرورگر سعی میکند حداقل هر 16.66 میلیثانیه یک فریم را برنامهریزی کند (برای اطمینان از بهروزرسانیهای روان)، یا پس از یک کار با اولویت بالا مانند مدیریت ورودی (برای اطمینان از بهروزرسانیهای پاسخگو). با این حال، اگر هیچ ورودی وجود نداشته باشد - و یا سایر وظایف با اولویت بالا - اما یک صف از وظایف دیگر وجود داشته باشد، مرورگر معمولاً فریم فعلی را به خوبی از 16.66 میلیثانیه گذشته است، مهم نیست که وظایف در آن چقدر به خوبی تقسیم شده باشند. یعنی مرورگر همیشه سعی میکند ورودیها را اولویتبندی کند، اما ممکن است صفی از وظایف را نسبت به بهروزرسانیهای رندر انتخاب کند. این به دلیل گران بودن رندر است، بنابراین پردازش یک کار رندر ترکیبی برای چندین کار معمولاً منجر به کاهش کلی کار می شود.
بنابراین، فریمهای انیمیشن طولانی با blockingDuration
کم یا صفر باید همچنان به ورودی پاسخ دهند. بنابراین، کاهش یا حذف blockingDuration
با شکستن وظایف طولانی، کلیدی برای بهبود پاسخگویی است که توسط INP اندازهگیری میشود.
با این حال، بسیاری از فریمهای انیمیشن طولانی، بدون در نظر گرفتن blockingDuration
مدت زمان بهروزرسانیهای رابط کاربری را نشان میدهد که با تأخیر مواجه میشوند و بنابراین همچنان میتوانند بر روان بودن تأثیر بگذارند و منجر به احساس تأخیر در رابط کاربری برای پیمایش یا انیمیشنها شوند، حتی اگر این موارد برای پاسخدهی کمتر مشکلی ایجاد کنند. اندازه گیری شده توسط INP برای درک مسائل در این زمینه به duration
نگاه کنید، اما بهینه سازی آنها می تواند دشوارتر باشد زیرا شما نمی توانید این مشکل را با جدا کردن کار حل کنید، بلکه باید کار را کاهش دهید.
زمان بندی فریم
مُهرهای زمانی که قبلاً ذکر شد، امکان تقسیم فریم طولانی انیمیشن را به زمانبندی فراهم میکند:
زمان بندی | محاسبه |
---|---|
زمان شروع | startTime |
زمان پایان | startTime + duration |
مدت زمان کار | renderStart ? renderStart - startTime : duration |
مدت زمان رندر | renderStart ? (startTime + duration) - renderStart: 0 |
رندر: مدت زمان قبل از طرح | styleAndLayoutStart ? styleAndLayoutStart - renderStart : 0 |
رندر: مدت زمان سبک و چیدمان | styleAndLayoutStart ? (startTime + duration) - styleAndLayoutStart : 0 |
انتساب فیلمنامه بهتر
نوع ورودی long-animation-frame
شامل داده های انتساب بهتر هر اسکریپت است که به یک قاب انیمیشن طولانی کمک می کند (برای اسکریپت های بیشتر از 5 میلی ثانیه).
مشابه با Long Tasks API، این مورد در آرایهای از ورودیهای انتساب ارائه میشود که هر کدام به شرح زیر است:
-
name
وEntryType
هر دوscript
برمیگردانند. - یک
invoker
معنادار، که نشان میدهد چگونه اسکریپت فراخوانی شده است (به عنوان مثال،'IMG#id.onload'
،'Window.requestAnimationFrame'
یا'Response.json.then'
). -
invokerType
نقطه ورود اسکریپت:-
user-callback
: یک پاسخ تماس شناخته شده ثبت شده از یک API پلتفرم وب (به عنوان مثال،setTimeout
،requestAnimationFrame
). -
event-listener
: شنونده یک رویداد پلتفرم (مثلاًclick
،load
،keyup
). -
resolve-promise
: Handler یک وعده پلتفرم (مثلاfetch()
. توجه داشته باشید که در مورد وعدهها، همه کنترلکنندههای همان وعدهها به عنوان یک «اسکریپت» با هم ترکیب میشوند).
-
reject-promise
: طبقresolve-promise
، اما برای رد. -
classic-script
: ارزیابی اسکریپت (به عنوان مثال،<script>
یاimport()
) -
module-script
: همانندclassic-script
، اما برای اسکریپت های ماژول.
-
- داده های زمان بندی را برای آن اسکریپت جدا کنید:
-
startTime
: زمانی که تابع ورودی فراخوانی شد. -
duration
: مدت زمان بینstartTime
و زمانی که پردازش صف ریز وظیفه بعدی به پایان رسید. -
executionStart
: زمان پس از کامپایل. -
forcedStyleAndLayoutDuration
: کل زمان صرف شده برای پردازش طرح و استایل اجباری در داخل این تابع (به thrashing مراجعه کنید). -
pauseDuration
: کل زمان صرف شده در "مکث" عملیات همزمان (هشدار، XHR همزمان).
-
- جزئیات منبع اسکریپت:
-
sourceURL
: نام منبع اسکریپت در صورت وجود (یا خالی در صورت یافت نشدن). -
sourceFunctionName
: نام تابع اسکریپت که در دسترس است (یا خالی اگر یافت نشد). -
sourceCharPosition
: موقعیت کاراکتر اسکریپت در صورت موجود بودن (یا -1 در صورت یافت نشدن).
-
-
windowAttribution
: محفظه (سند سطح بالا، یا یک<iframe>
) که قاب انیمیشن طولانی در آن قرار دارد. -
window
: ارجاع به پنجره همان منبع.
در صورت ارائه، ورودیهای منبع به توسعهدهندگان اجازه میدهد تا دقیقاً بدانند که هر اسکریپت در قاب طولانی انیمیشن چگونه فراخوانی شده است، تا موقعیت کاراکتر در اسکریپت فراخوان. این مکان دقیق را در یک منبع جاوا اسکریپت نشان می دهد که منجر به قاب طولانی انیمیشن می شود.
نمونهای از ورودی اجرای long-animation-frame
یک مثال کامل برای ورود به پرفورمنس long-animation-frame
، که شامل یک اسکریپت واحد است، به شرح زیر است:
{
"blockingDuration": 0,
"duration": 60,
"entryType": "long-animation-frame",
"firstUIEventTimestamp": 11801.099999999627,
"name": "long-animation-frame",
"renderStart": 11858.800000000745,
"scripts": [
{
"duration": 45,
"entryType": "script",
"executionStart": 11803.199999999255,
"forcedStyleAndLayoutDuration": 0,
"invoker": "DOMWindow.onclick",
"invokerType": "event-listener",
"name": "script",
"pauseDuration": 0,
"sourceURL": "https://web.dev/js/index-ffde4443.js",
"sourceFunctionName": "myClickHandler",
"sourceCharPosition": 17796,
"startTime": 11803.199999999255,
"window": [Window object],
"windowAttribution": "self"
}
],
"startTime": 11802.400000000373,
"styleAndLayoutStart": 11858.800000000745
}
همانطور که مشاهده می شود، این مقدار بی سابقه ای از داده ها را در اختیار وب سایت ها قرار می دهد تا بتوانند علت به روز رسانی رندر تاخیری را درک کنند.
از Long Animation Frames API در این زمینه استفاده کنید
ابزارهایی مانند Chrome DevTools و Lighthouse - اگرچه برای کشف و بازتولید مسائل مفید هستند - ابزارهای آزمایشگاهی هستند که ممکن است جنبههای مهم تجربه کاربر را که فقط دادههای میدانی میتوانند ارائه کنند، از دست بدهند.
Long Animation Frames API طراحی شده است تا در میدان مورد استفاده قرار گیرد تا دادههای زمینهای مهم برای تعاملات کاربر را جمعآوری کند که Long Tasks API قادر به انجام آن نبود. این می تواند به شما در شناسایی و بازتولید مسائلی با تعامل که ممکن است در غیر این صورت کشف نکرده باشید، کمک کند.
قابلیت شناسایی Long Animation Frames API
برای بررسی اینکه آیا API پشتیبانی می شود می توانید از کد زیر استفاده کنید:
if (PerformanceObserver.supportedEntryTypes.includes('long-animation-frame')) {
// Monitor LoAFs
}
پیوند به طولانی ترین تعامل INP
واضح ترین مورد استفاده برای Long Animation Frames API کمک به تشخیص و رفع مشکلات Interaction to Next Paint (INP) است، و این یکی از دلایل کلیدی تیم Chrome بود که این API را توسعه داد. یک INP خوب جایی است که تمام فعل و انفعالات در 200 میلی ثانیه یا کمتر از زمان تعامل تا زمانی که فریم نقاشی شود پاسخ داده می شود، و از آنجایی که Long Animation Frames API تمام فریم هایی را که 50 میلی ثانیه یا بیشتر طول می کشند اندازه گیری می کند، اکثر INP های مشکل ساز باید شامل داده های LoAF باشند تا به شما در تشخیص کمک کنند. آن فعل و انفعالات
"INP LoAF" LoAF است که شامل تعامل INP است، همانطور که در نمودار زیر نشان داده شده است:
در برخی موارد ممکن است که یک رویداد INP دو LoAF را در بر بگیرد—معمولاً اگر تعامل پس از شروع بخش رندر فریم قبلی توسط فریم اتفاق بیفتد و بنابراین کنترل کننده رویداد در فریم بعدی پردازش میشود:
حتی ممکن است در برخی شرایط نادر، بیش از دو LoAF را در بر گیرد.
ثبت دادههای LoAF(های) مرتبط با تعامل INP به شما امکان میدهد اطلاعات بیشتری در مورد تعامل INP برای کمک به تشخیص آن به دست آورید. این به ویژه برای درک تاخیر ورودی مفید است: همانطور که می بینید چه اسکریپت های دیگری در آن فریم اجرا می شدند.
همچنین درک مدت زمان پردازش غیرقابل توضیح و تأخیر ارائه میتواند مفید باشد اگر کنترلکنندههای رویداد شما مقادیری را که برای آنها مشاهده میشود بازتولید نمیکنند، زیرا ممکن است اسکریپتهای دیگری برای کاربران شما در حال اجرا باشند که ممکن است در آزمایش خود شما لحاظ نشده باشند.
هیچ API مستقیمی برای پیوند دادن یک ورودی INP با ورودی یا ورودی های LoAF مربوط به آن وجود ندارد، اگرچه می توان این کار را به صورت کد با مقایسه زمان شروع و پایان هر کدام انجام داد (به اسکریپت مثال WhyNp مراجعه کنید). کتابخانه web-vitals
شامل تمام LoAF های متقاطع در ویژگی longAnimationFramesEntries
رابط انتساب INP از نسخه 4 است.
هنگامی که ورودی یا ورودی های LoAF را پیوند دادید، می توانید اطلاعاتی را با انتساب INP اضافه کنید. شی scripts
حاوی برخی از ارزشمندترین اطلاعات است، زیرا می تواند نشان دهد که چه چیز دیگری در آن فریم ها در حال اجرا است، بنابراین بازگرداندن آن داده ها به سرویس تجزیه و تحلیل شما به شما این امکان را می دهد که بیشتر در مورد چرایی کندی تعاملات درک کنید.
گزارش LoAF ها برای تعامل INP راه خوبی برای یافتن مهم ترین مسائل تعاملی در صفحه شما است. هر کاربر ممکن است با صفحه شما تعامل متفاوتی داشته باشد و با حجم کافی از داده های انتساب INP، تعدادی از مشکلات احتمالی در داده های انتساب INP گنجانده می شود. این به شما امکان می دهد اسکریپت ها را بر اساس حجم مرتب کنید تا ببینید کدام اسکریپت با INP کند مرتبط است.
دادههای طولانیتر انیمیشن را به نقطه پایانی تجزیه و تحلیل گزارش دهید
یکی از نکات منفی نگاه کردن به LoAF(های) INP این است که ممکن است سایر زمینههای بالقوه برای بهبودهایی را که ممکن است باعث مشکلات INP در آینده شود از دست بدهید. این میتواند منجر به احساس تعقیب دنبال خود شود، جایی که مشکل INP را برطرف میکنید و انتظار دارید پیشرفت بزرگی را مشاهده کنید، فقط برای یافتن اینکه کندترین تعامل بعدی فقط مقدار کمی بهتر از آن است، بنابراین INP شما بهبود چندانی نمییابد.
بنابراین به جای اینکه فقط به INP LoAF نگاه کنید، ممکن است بخواهید همه LoAF ها را در طول عمر صفحه در نظر بگیرید:
با این حال، هر ورودی LoAF حاوی داده های قابل توجهی است، بنابراین احتمالاً می خواهید تجزیه و تحلیل خود را فقط به برخی از LoAF ها محدود کنید. علاوه بر این، از آنجایی که ورودی های فریم انیمیشن طولانی می تواند بسیار بزرگ باشد، توسعه دهندگان باید تصمیم بگیرند که چه داده هایی از ورودی باید به تجزیه و تحلیل ارسال شود. به عنوان مثال، زمانهای خلاصه ورودی و شاید نامهای اسکریپت، یا حداقل مجموعه دیگری از دادههای زمینهای دیگر که ممکن است ضروری تلقی شوند.
برخی از الگوهای پیشنهادی برای کاهش حجم دادههای فریم انیمیشن طولانی عبارتند از:
- فریم های طولانی انیمیشن را با تعامل مشاهده کنید
- فریم های انیمیشن طولانی با مدت زمان مسدود شدن بالا را مشاهده کنید
- برای بهبود نرمی، فریمهای طولانی انیمیشن را در طول بهروزرسانیهای مهم رابط کاربری مشاهده کنید
- بدترین فریم های طولانی انیمیشن را مشاهده کنید
- الگوهای رایج در فریم های انیمیشن بلند را شناسایی کنید
اینکه کدام یک از این الگوها برای شما بهتر عمل میکند، بستگی به این دارد که چقدر در مسیر بهینهسازی شما قرار گرفتهاید و فریمهای انیمیشن طولانی چقدر رایج هستند. برای سایتی که قبلاً هرگز برای پاسخگویی بهینه سازی نشده است، ممکن است LoAF های زیادی وجود داشته باشد که بخواهید فقط به LoAF ها با تعامل محدود کنید، یا آستانه بالایی را تعیین کنید، یا فقط به بدترین آنها نگاه کنید.
همانطور که مشکلات رایج پاسخگویی خود را حل می کنید، می توانید این را با محدود نکردن فقط به تعاملات یا مدت زمان مسدود کردن بالا یا با کاهش آستانه گسترش دهید.
فریم های طولانی انیمیشن را با تعامل مشاهده کنید
برای به دست آوردن اطلاعاتی فراتر از قاب انیمیشن طولانی INP، میتوانید همه LoAFها را با فعل و انفعالات (که میتوان با حضور یک مقدار firstUIEventTimestamp
تشخیص داد) با مدت blockingDuration
بالا مشاهده کرد.
این همچنین میتواند روش سادهتری برای نظارت بر INP LoAFها به جای تلاش برای مرتبط کردن این دو باشد، که میتواند پیچیدهتر باشد. در بیشتر موارد، این شامل INP LoAF برای یک بازدید معین میشود، و در موارد نادری که باز هم نشان داده نمیشود، باز هم فعل و انفعالات طولانی را نشان میدهد که رفع آنها مهم است، زیرا ممکن است تعامل INP برای سایر کاربران باشد.
کد زیر تمام ورودیهای LoAF را با مدت blockingDuration
بیش از 100 میلیثانیه که در آن تعامل در طول فریم رخ داده است، ثبت میکند. 100 در اینجا انتخاب می شود زیرا کمتر از آستانه INP "خوب" 200 میلی ثانیه است. بسته به نیاز خود می توانید مقدار بالاتر یا کمتری را انتخاب کنید.
const REPORTING_THRESHOLD_MS = 100;
const observer = new PerformanceObserver(list => {
for (const entry of list.getEntries()) {
if (entry.blockingDuration > REPORTING_THRESHOLD_MS &&
entry.firstUIEventTimestamp > 0
) {
// Example here logs to console, but could also report back to analytics
console.log(entry);
}
}
});
observer.observe({ type: 'long-animation-frame', buffered: true });
فریم های انیمیشن طولانی با مدت زمان مسدود شدن بالا را مشاهده کنید
به عنوان پیشرفتی برای مشاهده تمام فریم های انیمیشن طولانی با تعامل، ممکن است بخواهید به تمام فریم های انیمیشن طولانی با مدت زمان مسدود شدن بالا نگاه کنید. اگر کاربر در طول این فریم های انیمیشن طولانی تعامل داشته باشد، اینها مشکلات احتمالی INP را نشان می دهد.
کد زیر تمام ورودیهای LoAF را با مدت زمان مسدود کردن بیش از 100 میلیثانیه که در آن تعامل در طول فریم رخ داده است، ثبت میکند. 100 در اینجا انتخاب شده است زیرا کمتر از آستانه INP "خوب" 200 میلی ثانیه است تا به شناسایی فریم های مشکل بالقوه کمک کند، در حالی که تعداد فریم های انیمیشن طولانی گزارش شده را به حداقل می رساند. بسته به نیاز خود می توانید مقدار بالاتر یا کمتری را انتخاب کنید.
const REPORTING_THRESHOLD_MS = 100;
const observer = new PerformanceObserver(list => {
for (const entry of list.getEntries()) {
if (entry.blockingDuration > REPORTING_THRESHOLD_MS) {
// Example here logs to console, but could also report back to analytics
console.log(entry);
}
}
});
observer.observe({ type: 'long-animation-frame', buffered: true });
برای بهبود نرمی، فریمهای طولانی انیمیشن را در طول بهروزرسانیهای مهم رابط کاربری مشاهده کنید
همانطور که قبلا ذکر شد، نگاه کردن به فریمهای انیمیشن طولانی مدت مسدود شدن بالا میتواند به پاسخگویی ورودی کمک کند. اما برای صاف بودن باید به تمام فریم های انیمیشن طولانی با duration
طولانی نگاه کنید.
از آنجایی که این می تواند بسیار پر سر و صدا باشد، ممکن است بخواهید اندازه گیری آنها را به نقاط کلیدی با الگوی زیر محدود کنید:
const REPORTING_THRESHOLD_MS = 100;
const observer = new PerformanceObserver(list => {
if (measureImportantUIupdate) {
for (const entry of list.getEntries()) {
if (entry.duration > REPORTING_THRESHOLD_MS) {
// Example here logs to console, but could also report back to analytics
console.log(entry);
}
}
}
});
observer.observe({ type: 'long-animation-frame', buffered: true });
async function doUIUpdatesWithMeasurements() {
measureImportantUIupdate = true;
await doUIUpdates();
measureImportantUIupdate = false;
}
بدترین فریم های طولانی انیمیشن را مشاهده کنید
به جای داشتن آستانه تعیین شده، سایتها ممکن است بخواهند دادهها را در طولانیترین قاب انیمیشن (یا فریمها) جمعآوری کنند، تا حجم دادههایی را که باید نشان داده شود، کاهش دهند. بنابراین مهم نیست که یک صفحه چند فریم انیمیشن طولانی را تجربه می کند، تنها اطلاعات مربوط به بدترین فریم های متحرک، پنج، ده، یا هر تعداد فریم های طولانی انیمیشنی که کاملا ضروری است، نشان داده می شود.
MAX_LOAFS_TO_CONSIDER = 10;
let longestBlockingLoAFs = [];
const observer = new PerformanceObserver(list => {
longestBlockingLoAFs = longestBlockingLoAFs.concat(list.getEntries()).sort(
(a, b) => b.blockingDuration - a.blockingDuration
).slice(0, MAX_LOAFS_TO_CONSIDER);
});
observer.observe({ type: 'long-animation-frame', buffered: true });
این استراتژیها را نیز میتوان با هم ترکیب کرد - فقط به 10 بدترین LoAF با فعل و انفعالات طولانیتر از 100 میلیثانیه نگاه کنید.
در زمان مناسب ( به طور ایده آل در رویداد visibilitychange
) چراغ راهنما به تجزیه و تحلیل باز می گردد. برای آزمایش محلی میتوانید بهطور دورهای از console.table
استفاده کنید:
console.table(longestBlockingLoAFs);
الگوهای رایج در فریم های انیمیشن بلند را شناسایی کنید
یک استراتژی جایگزین این است که به اسکریپتهای رایجی که بیشترین نمایش را در فریمهای انیمیشن طولانی دارند نگاه کنیم. داده ها را می توان در سطح اسکریپت و موقعیت شخصیت برای شناسایی مجرمان تکراری گزارش کرد.
این ممکن است بهویژه برای پلتفرمهای قابل تنظیم که در آنها مضامین یا افزونههایی که باعث مشکلات عملکردی میشوند، در تعدادی از سایتها شناسایی شوند، خوب عمل کند.
زمان اجرای اسکریپتهای متداول - یا منشأ شخص ثالث - در فریمهای انیمیشن بلند را میتوان خلاصه کرد و برای شناسایی مشارکتکنندگان مشترک در فریمهای انیمیشن طولانی در یک سایت یا مجموعهای از سایتها، گزارش داد. به عنوان مثال برای نگاه کردن به URL ها:
const observer = new PerformanceObserver(list => {
const allScripts = list.getEntries().flatMap(entry => entry.scripts);
const scriptSource = [...new Set(allScripts.map(script => script.sourceURL))];
const scriptsBySource= scriptSource.map(sourceURL => ([sourceURL,
allScripts.filter(script => script.sourceURL === sourceURL)
]));
const processedScripts = scriptsBySource.map(([sourceURL, scripts]) => ({
sourceURL,
count: scripts.length,
totalDuration: scripts.reduce((subtotal, script) => subtotal + script.duration, 0)
}));
processedScripts.sort((a, b) => b.totalDuration - a.totalDuration);
// Example here logs to console, but could also report back to analytics
console.table(processedScripts);
});
observer.observe({type: 'long-animation-frame', buffered: true});
و مثال این خروجی این است:
(index) | sourceURL | count | totalDuration |
---|---|---|---|
0 | 'https://example.consent.com/consent.js' | 1 | 840 |
1 | 'https://example.com/js/analytics.js' | 7 | 628 |
2 | 'https://example.chatapp.com/web-chat.js' | 1 | 5 |
از Long Animation Frames API در ابزارسازی استفاده کنید
API همچنین به توسعه دهندگان ابزار اضافی برای اشکال زدایی محلی اجازه می دهد. در حالی که برخی ابزارها مانند Lighthouse و Chrome DevTools توانستهاند بسیاری از این دادهها را با استفاده از جزئیات ردیابی سطح پایینتر جمعآوری کنند، داشتن این API سطح بالاتر میتواند به ابزارهای دیگر اجازه دسترسی به این دادهها را بدهد.
داده های فریم های انیمیشن بلند سطحی را در DevTools مشاهده کنید
میتوانید با استفاده از API performance.measure()
فریمهای انیمیشن طولانی را در DevTools نشان دهید، که سپس در مسیر زمانبندی کاربر DevTools در ردیابی عملکرد نمایش داده میشوند تا نشان دهند که تلاشهای خود را برای بهبود عملکرد کجا متمرکز کنید. با استفاده از DevTools Extensibility API این موارد حتی می توانند در مسیر خود نشان داده شوند:
const observer = new PerformanceObserver((list) => {
for (const entry of list.getEntries()) {
performance.measure('LoAF', {
start: entry.startTime,
end: entry.startTime + entry.duration,
detail: {
devtools: {
dataType: "track-entry",
track: "Long animation frames",
trackGroup: "Performance Timeline",
color: "tertiary-dark",
tooltipText: 'LoAF'
}
}
});
}
});
observer.observe({ type: 'long-animation-frame', buffered: true });
فریمهای طولانیمدت انیمیشن احتمالاً در خود DevTools گنجانده میشوند، اما قطعه کد قبلی به آن اجازه میدهد تا در این مدت در آنجا ظاهر شود.
اولین ورودی در شکل قبلی همچنین نشان میدهد که مرورگر به جای رندر کردن بین آنها، چندین کار را با هم در یک قاب انیمیشن طولانی پردازش کرده است. همانطور که قبلاً ذکر شد این می تواند زمانی اتفاق بیفتد که وظایف ورودی با اولویت بالا وجود ندارد، اما یک صف از وظایف وجود دارد. اولین کار طولانی دارای برخی بهروزرسانیهای رندر برای تکمیل است (در غیر این صورت، فریم انیمیشن طولانی فعلی پس از آن بازنشانی میشود و یک کار جدید با کار بعدی شروع میشود)، اما مرورگر بهجای انجام فوری آن رندر، تعدادی از موارد را پردازش کرده است. وظایف اضافی را انجام داد و تنها پس از آن وظیفه رندر طولانی را انجام داد و فریم طولانی انیمیشن را پایان داد. این کار سودمندی نگاه کردن به فریم های طولانی انیمیشن در DevTools را به جای کارهای طولانی برای کمک به شناسایی رندرهای تاخیری نشان می دهد.
از دادههای فریمهای انیمیشن طولانی در سایر ابزارهای توسعهدهنده استفاده کنید
اکنون همچنین دادههای فریم انیمیشن طولانی را برای هر تماس INP و هر تعامل نشان میدهد:
از داده های فریم های انیمیشن بلند در ابزارهای تست خودکار استفاده کنید
به طور مشابه، ابزارهای تست خودکار در خطوط لوله CI/CD میتوانند با اندازهگیری فریمهای طولانی انیمیشن در حین اجرای مجموعههای آزمایشی مختلف، جزئیات مربوط به مشکلات عملکرد بالقوه را نشان دهند.
سوالات متداول
برخی از سوالات متداول در مورد این API عبارتند از:
چرا روی Long Tasks API فقط تمدید یا تکرار نمی شود؟
این یک نگاه جایگزین به گزارش یک اندازه گیری مشابه – اما در نهایت متفاوت – از مسائل احتمالی پاسخگویی است. مهم است که اطمینان حاصل شود که سایتهای متکی به Long Tasks API به کار خود ادامه میدهند تا از ایجاد اختلال در موارد استفاده موجود جلوگیری شود.
در حالی که Long Tasks API ممکن است از برخی از ویژگیهای LoAF (مانند یک مدل انتساب بهتر) بهره مند شود، ما معتقدیم که تمرکز بر فریمها به جای وظایف، مزایای زیادی را ارائه میکند که این API را اساساً متفاوت از Long Tasks API موجود میسازد.
چرا ورودی های اسکریپت ندارم؟
این ممکن است نشان دهد که فریم طولانی انیمیشن به دلیل جاوا اسکپت نیست، بلکه به دلیل کار رندر بزرگ است.
این همچنین می تواند زمانی اتفاق بیفتد که فریم طولانی انیمیشن به دلیل جاوا اسکریپت باشد ، اما به دلایل مختلف حفظ حریم خصوصی همانطور که قبلا ذکر شد (در درجه اول اینکه جاوا اسکریپت متعلق به صفحه نیست) نمی توان انتساب اسکریپت را ارائه کرد.
چرا ورودی های اسکریپت را دارم اما اطلاعات منبع ندارد یا محدود است؟
این ممکن است به دلایل مختلفی اتفاق بیفتد، از جمله اینکه منبع خوبی برای اشاره وجود ندارد .
اطلاعات اسکریپت همچنین برای اسکریپتهای no-cors cross-origin
محدود خواهد شد، اگرچه این مشکل را میتوان با واکشی آن اسکریپتها با استفاده از CORS با افزودن crossOrigin = "anonymous"
به تماس <script>
حل کرد.
به عنوان مثال، اسکریپت پیش فرض Google Tag Manager برای افزودن به صفحه:
<!-- Google Tag Manager -->
<script>(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
})(window,document,'script','dataLayer','GTM-XXXXXXX');</script>
<!-- End Google Tag Manager -->
می توان آن را برای افزودن j.crossOrigin = "anonymous"
ارتقا داد تا امکان ارائه جزئیات انتساب کامل برای GTM فراهم شود.
آیا این جایگزین Long Tasks API خواهد شد؟
در حالی که ما معتقدیم Long Animation Frames API API بهتر و کاملتری برای اندازهگیری کارهای طولانی است، در حال حاضر، هیچ برنامهای برای منسوخ کردن Long Tasks API وجود ندارد.
بازخورد می خواستم
بازخورد را می توان در لیست مشکلات GitHub ارائه کرد، یا اشکالات در اجرای Chrome از API را می توان در ردیاب مشکل کروم ثبت کرد.
نتیجه گیری
Long Animation Frames API یک API جدید و هیجان انگیز با مزایای بالقوه زیادی نسبت به Long Tasks API قبلی است.
ثابت شده است که این یک ابزار کلیدی برای رسیدگی به مسائل مربوط به پاسخگویی است که توسط INP اندازه گیری می شود. INP معیاری چالش برانگیز برای بهینه سازی است و این API راهی است که تیم Chrome به دنبال تسهیل شناسایی و رسیدگی به مشکلات برای توسعه دهندگان است.
دامنه Long Animation Frames API فراتر از فقط INP است، و می تواند به شناسایی دلایل دیگر به روز رسانی کند کمک کند که می تواند بر روان بودن کلی تجربه کاربری یک وب سایت تأثیر بگذارد.
قدردانی
تصویر کوچک توسط هنری بی در Unsplash .
،Long Animation Frames API (با تلفظ LoAF Lo-Af) بهروزرسانی Long Tasks API است تا درک بهتری از بهروزرسانیهای رابط کاربر آهسته (UI) ارائه دهد. این میتواند برای شناسایی فریمهای پویانمایی آهسته که احتمالاً بر معیار Interaction to Next Paint (INP) Core Web Vital که میزان پاسخدهی را اندازهگیری میکند، تأثیر میگذارد، یا برای شناسایی سایر جابهجاییهای رابط کاربری که بر صافی تأثیر میگذارند، مفید باشد.
وضعیت API
پس از آزمایش اولیه از Chrome 116 به Chrome 122 ، LoAF API از Chrome 123 ارسال شد.
پس زمینه: Long Tasks API
Long Animation Frames API جایگزینی برای Long Tasks API است که مدتی است (از Chrome 58) در Chrome موجود است. همانطور که از نامش پیداست، Long Task API به شما امکان می دهد کارهای طولانی را نظارت کنید، کارهایی که رشته اصلی را برای 50 میلی ثانیه یا بیشتر اشغال می کنند. کارهای طولانی را می توان با استفاده از رابط PerformanceLongTaskTiming
، با PeformanceObserver
مانیتور کرد:
const observer = new PerformanceObserver((list) => {
console.log(list.getEntries());
});
observer.observe({ type: 'longtask', buffered: true });
کارهای طولانی احتمالا باعث مشکلات پاسخگویی می شوند. اگر کاربر سعی کند با یک صفحه تعامل داشته باشد - به عنوان مثال، روی یک دکمه کلیک کند یا یک منو باز کند - اما موضوع اصلی در حال حاضر با یک کار طولانی سروکار دارد، در این صورت تعامل کاربر در انتظار تکمیل آن کار به تاخیر می افتد .
برای بهبود پاسخگویی، اغلب توصیه می شود کارهای طولانی را از بین ببرید . اگر هر کار طولانی به جای آن به مجموعه ای از وظایف متعدد و کوچکتر تقسیم شود، ممکن است اجازه دهد تا وظایف مهم تری در بین آنها اجرا شود تا از تأخیر قابل توجه در پاسخگویی به تعاملات جلوگیری شود.
بنابراین هنگام تلاش برای بهبود پاسخگویی، اولین تلاش اغلب اجرای یک ردیابی عملکرد و بررسی وظایف طولانی است. این میتواند از طریق یک ابزار ممیزی مبتنی بر آزمایشگاه مانند Lighthouse (که دارای ممیزی از کارهای طولانی رشته اصلی اجتناب شود )، یا با مشاهده کارهای طولانی در ابزار توسعه کروم باشد.
آزمایش مبتنی بر آزمایشگاه اغلب محل شروع ضعیفی برای شناسایی مسائل مربوط به پاسخگویی است، زیرا این ابزارها ممکن است شامل تعاملات نباشند—در صورت وجود، زیرمجموعه کوچکی از تعاملات احتمالی هستند. در حالت ایدهآل، میتوانید دلایل کندی تعاملات را در این زمینه اندازهگیری کنید.
کاستی های Long Tasks API
اندازهگیری کارهای طولانی در میدان با استفاده از مشاهدهگر عملکرد فقط تا حدودی مفید است. در واقع، اطلاعات زیادی فراتر از این که یک کار طولانی اتفاق افتاده است، و اینکه چقدر طول کشیده است، نمی دهد.
ابزارهای نظارت بر کاربر واقعی (RUM) اغلب از این برای افزایش تعداد یا مدت کارهای طولانی یا شناسایی صفحاتی که در آنها انجام میشوند استفاده میکنند - اما بدون جزئیات اساسی در مورد علت انجام کار طولانی، این فقط کاربرد محدودی دارد. Long Tasks API فقط یک مدل انتساب اولیه دارد، که در بهترین حالت فقط به شما میگوید ظرفی که وظیفه طولانی در آن اتفاق افتاده است (سند سطح بالا یا یک <iframe>
)، اما نه اسکریپت یا تابعی که آن را فراخوانی کرده است، همانطور که نشان داده شده است یک ورودی معمولی:
{
"name": "unknown",
"entryType": "longtask",
"startTime": 31.799999997019768,
"duration": 136,
"attribution": [
{
"name": "unknown",
"entryType": "taskattribution",
"startTime": 0,
"duration": 0,
"containerType": "window",
"containerSrc": "",
"containerId": "",
"containerName": ""
}
]
}
Long Tasks API نیز یک نمای ناقص است، زیرا ممکن است برخی از وظایف مهم را نیز حذف کند. برخی بهروزرسانیها - مانند رندر کردن - در وظایف جداگانهای اتفاق میافتند که در حالت ایدهآل باید همراه با اجرای قبلی گنجانده شوند که باعث شد آن بهروزرسانی بهدقت «کل کار» آن تعامل را اندازهگیری کند. برای جزئیات بیشتر در مورد محدودیتهای تکیه بر وظایف، به بخش «جایی که کارهای طولانی کوتاه میآیند» توضیحدهنده مراجعه کنید.
مسئله نهایی این است که اندازه گیری کارهای طولانی فقط در مورد کارهای فردی گزارش می دهد که بیش از حد مجاز 50 میلی ثانیه طول می کشد. یک فریم انیمیشن میتواند از چندین کار کوچکتر از این محدودیت 50 میلیثانیهای تشکیل شود، اما در مجموع همچنان توانایی مرورگر را برای رندر کردن مسدود میکند.
Long Animation Frames API
قاب های انیمیشن طولانی API (LOAF) یک API جدید است که به دنبال رفع برخی از کاستی های API کارهای طولانی است تا توسعه دهندگان بتوانند بینش های عملی تری کسب کنند تا به مشکلات پاسخگویی و بهبود INP کمک کنند ، و همچنین بینش در مورد مسائل مربوط به صافی کسب کنند. .
پاسخگویی خوب بدان معنی است که یک صفحه به سرعت به تعامل های ایجاد شده با آن پاسخ می دهد. این شامل قادر به نقاشی هرگونه به روزرسانی مورد نیاز کاربر به موقع و جلوگیری از جلوگیری از وقوع این به روزرسانی ها است. برای INP ، توصیه می شود در 200 میلی ثانیه یا کمتر پاسخ دهید ، اما برای سایر به روزرسانی ها (به عنوان مثال انیمیشن ها) حتی 200 میلی ثانیه ممکن است خیلی طولانی باشد.
قاب های انیمیشن طولانی API یک روش جایگزین برای اندازه گیری کار مسدود کننده است. به جای اندازه گیری وظایف فردی ، قاب های انیمیشن طولانی API - همانطور که نام آن پیداست - قاب های انیمیشن طولانی را اندازه گیری می کند. یک قاب انیمیشن طولانی زمانی است که یک به روزرسانی رندر فراتر از 50 میلی ثانیه به تأخیر می افتد (همان آستانه API کارهای طولانی).
قاب های انیمیشن طولانی از شروع کارهایی که به یک رندر نیاز دارند اندازه گیری می شوند. جایی که اولین کار در یک قاب انیمیشن بالقوه بالقوه نیازی به رندر ندارد ، قاب انیمیشن طولانی پس از اتمام کار غیر ارائه دهنده به پایان می رسد و یک قاب جدید انیمیشن طولانی بالقوه با کار بعدی آغاز می شود. چنین قاب انیمیشن طولانی غیر رندر هنوز هم در قاب های انیمیشن طولانی API گنجانده شده است که بیشتر از 50 میلی ثانیه (با زمان renderStart
0) برای اندازه گیری کار مسدود کننده بالقوه امکان پذیر است.
قاب های انیمیشن طولانی می توانند به روشی مشابه به عنوان کارهای طولانی با یک PerformanceObserver
مشاهده شوند ، اما به جای آن با نگاه به نوع long-animation-frame
نگاه می کنند:
const observer = new PerformanceObserver((list) => {
console.log(list.getEntries());
});
observer.observe({ type: 'long-animation-frame', buffered: true });
قاب های انیمیشن طولانی قبلی نیز می توانند از جدول زمانی عملکرد مانند SO پرسیده شوند:
const loafs = performance.getEntriesByType('long-animation-frame');
با این حال ، برای ورودی های عملکردی یک maxBufferSize
وجود دارد که پس از آن ورودی های جدیدتر از بین می روند ، بنابراین رویکرد PerformanceObServer رویکرد توصیه شده است. اندازه بافر long-animation-frame
بر روی 200 تنظیم شده است ، همانند long-tasks
.
مزایای نگاه به فریم به جای کارها
مزیت اصلی نگاه کردن به این موضوع از دیدگاه فریم و نه یک دیدگاه وظایف ، این است که یک انیمیشن طولانی می تواند از هر تعداد کارهایی که به صورت تجمعی منجر به یک قاب انیمیشن طولانی شده اند ، ساخته شود. این نکته نهایی را که قبلاً ذکر شد ، می پردازد ، جایی که جمع بسیاری از کارهای کوچکتر و مسدود کننده قبل از یک قاب انیمیشن ممکن است توسط API کارهای طولانی ظاهر نشود.
مزیت بیشتر این دیدگاه جایگزین در مورد کارهای طولانی ، امکان ارائه خرابی زمان بندی کل فریم است. Loaf به جای اینکه فقط یک startTime
و duration
، مانند API کارهای طولانی را شامل شود ، شامل یک تفسیر بسیار دقیق تر از قسمت های مختلف مدت قاب است.
زمان و مدت زمان بندی قاب
-
startTime
: زمان شروع قاب انیمیشن طولانی نسبت به زمان شروع ناوبری. -
duration
: مدت زمان قاب انیمیشن طولانی (شامل زمان ارائه نیست). -
renderStart
: زمان شروع چرخه ارائه ، که شامل درخواست هایrequestAnimationFrame
، محاسبه سبک و چیدمان ، تغییر اندازه ناظر و تقاطع ناظر است. -
styleAndLayoutStart
: آغاز دوره زمانی که در محاسبات سبک و چیدمان صرف شده است. -
firstUIEventTimestamp
: زمان اولین رویداد UI (ماوس/صفحه کلید و غیره) که در طول این قاب انجام می شود. -
blockingDuration
: مدت زمان کل در میلی ثانیه که قاب انیمیشن می تواند پردازش ورودی یا سایر کارهای با اولویت بالا را مسدود کند.
توضیح در مورد blockingDuration
یک قاب انیمیشن طولانی ممکن است از تعدادی از کارها ساخته شود. blockingDuration
کل مدت زمان کار بیش از 50 میلی ثانیه (از جمله مدت زمان ارائه نهایی در طولانی ترین کار) است.
به عنوان مثال ، اگر یک قاب انیمیشن طولانی از دو کار 55 میلی ثانیه و 65 میلی ثانیه و به دنبال آن یک رندر 20 میلی ثانیه تشکیل شده باشد ، duration
آن تقریباً 140 میلی ثانیه با blockingDuration
(55 - 50) + (65 + 20) خواهد بود. - 50) = 40 میلی ثانیه. برای 40 میلی ثانیه در طول این قاب انیمیشن 140 میلی ثانیه ، این قاب از ورودی ورودی مسدود شده است.
آیا به duration
یا blockingDuration
نگاه کنید
برای نمایشگر مشترک 60 هرتز ، یک مرورگر سعی خواهد کرد حداقل هر 16.66 میلی ثانیه (برای اطمینان از بروزرسانی های صاف) یا بعد از یک کار با اولویت بالا مانند دست زدن به ورودی (برای اطمینان از به روزرسانی های پاسخگو) یک قاب را برنامه ریزی کند. با این حال ، اگر هیچ ورودی وجود نداشته باشد-دیگر کارهای اولویت بالا-اما یک صف کارهای دیگر وجود دارد ، مرورگر به طور معمول قاب فعلی را به خوبی از 16.66 میلی ثانیه ادامه می دهد ، مهم نیست که چقدر کارها را در آن قرار داده اند. یعنی ، مرورگر همیشه سعی در اولویت بندی ورودی ها خواهد داشت ، اما ممکن است تصمیم بگیرد که صف کارها را از طریق به روزرسانی ارائه دهد. این امر به این دلیل است که یک فرآیند گران قیمت است ، بنابراین پردازش یک کار ارائه دهنده ترکیبی برای چندین کار معمولاً منجر به کاهش کلی کار می شود.
بنابراین ، قاب های انیمیشن طولانی با blockingDuration
کم یا صفر باید همچنان پاسخگو به ورودی باشند. کاهش یا از بین بردن blockingDuration
با شکستن کارهای طولانی برای بهبود پاسخگویی به عنوان اندازه گیری شده توسط INP مهم است.
با این حال ، بسیاری از قاب های انیمیشن طولانی ، صرف نظر از blockingDuration
نشانگر به روزرسانی های UI که به تأخیر افتاده اند و بنابراین هنوز هم می توانند بر صافی تأثیر بگذارند و منجر به احساس رابط کاربری لاغر برای پیمایش یا انیمیشن شوند ، حتی اگر اینها کمتر مسئله ای برای پاسخگویی باشند به عنوان اندازه گیری شده توسط INP. برای درک مسائل موجود در این زمینه به duration
نگاه می کند ، اما این موارد می توانند بهینه سازی شوند زیرا شما نمی توانید با شکستن کار این مسئله را حل کنید ، اما در عوض باید کار را کاهش دهید.
زمان بندی
جدول زمانی که قبلاً ذکر شد ، اجازه می دهد تا قاب انیمیشن طولانی به زمان بندی تقسیم شود:
زمان بندی | محاسبه |
---|---|
زمان شروع | startTime |
زمان پایان | startTime + duration |
مدت کار | renderStart ? renderStart - startTime : duration |
مدت زمان بندی | renderStart ? (startTime + duration) - renderStart: 0 |
رندر: مدت قبل از لایه | styleAndLayoutStart ? styleAndLayoutStart - renderStart : 0 |
رندر: مدت زمان سبک و طرح | styleAndLayoutStart ? (startTime + duration) - styleAndLayoutStart : 0 |
انتساب اسکریپت بهتر
نوع ورود long-animation-frame
شامل داده های نسبت بهتر از هر اسکریپت است که به یک قاب انیمیشن طولانی (برای اسکریپت های طولانی تر از 5 میلی ثانیه) کمک می کند.
مشابه API کارهای طولانی ، این در مجموعه ای از ورودی های انتساب ارائه می شود که هر یک از آنها جزئیات:
- یک
name
وEntryType
هر دوscript
برمی گردانند. - یک
invoker
معنی دار ، نشان می دهد که چگونه این اسکریپت نامیده می شود (به عنوان مثال ،'IMG#id.onload'
،'Window.requestAnimationFrame'
یا'Response.json.then'
). -
invokerType
از نقطه ورود اسکریپت:-
user-callback
: یک تماس تلفنی شناخته شده از یک API پلت فرم وب (به عنوان مثال ،setTimeout
،requestAnimationFrame
) ثبت شده است. -
event-listener
: شنونده یک رویداد پلتفرم (به عنوان مثال ،click
،load
،keyup
). -
resolve-promise
: کنترل کننده یک پلتفرم وعده (به عنوان مثال ،fetch()
. توجه داشته باشید که در مورد وعده ها ، همه دستگیرندگان همان وعده ها به عنوان یک "اسکریپت" با هم مخلوط می شوند).
-
reject-promise
: مطابق باresolve-promise
، اما برای رد. -
classic-script
: ارزیابی اسکریپت (به عنوان مثال ،<script>
یاimport()
) -
module-script
: همانclassic-script
، اما برای اسکریپت های ماژول.
-
- داده های زمان بندی جداگانه برای آن اسکریپت:
-
startTime
: زمان استفاده از عملکرد ورود. -
duration
: مدت زمان بینstartTime
و هنگامی که صف میکروتاسک متعاقب آن پردازش تمام شده است. -
executionStart
: زمان بعد از تدوین. -
forcedStyleAndLayoutDuration
: کل زمان صرف شده برای پردازش طرح اجباری و سبک در این عملکرد (نگاه کنید به Thrashing ). -
pauseDuration
: کل زمان صرف شده در عملیات همزمان "مکث" (هشدار ، XHR همزمان).
-
- جزئیات منبع فیلمنامه:
-
sourceURL
: نام منبع اسکریپت در صورت وجود (یا خالی در صورت یافتن). -
sourceFunctionName
: نام عملکرد اسکریپت که در صورت موجود بودن (یا خالی در صورت یافتن). -
sourceCharPosition
: موقعیت کاراکتر اسکریپت که در آن موجود است (یا -1 در صورت یافتن).
-
-
windowAttribution
: کانتینر (سند سطح بالا ، یا<iframe>
) قاب انیمیشن طولانی در آن رخ داده است. -
window
: اشاره ای به پنجره همان منشأ.
در صورت ارائه ، ورودی های منبع به توسعه دهندگان این امکان را می دهد تا دقیقاً بدانند که چگونه هر اسکریپت در قاب انیمیشن طولانی فراخوانی شده است ، که به موقعیت کاراکتر در اسکریپت فراخوانی می رسد. این مکان دقیق را در یک منبع JavaScript که منجر به قاب انیمیشن طولانی شده است ، می دهد.
نمونه ای از یک ورود به عملکرد long-animation-frame
یک مثال کامل ورود به عملکرد long-animation-frame
، حاوی یک اسکریپت واحد ،:
{
"blockingDuration": 0,
"duration": 60,
"entryType": "long-animation-frame",
"firstUIEventTimestamp": 11801.099999999627,
"name": "long-animation-frame",
"renderStart": 11858.800000000745,
"scripts": [
{
"duration": 45,
"entryType": "script",
"executionStart": 11803.199999999255,
"forcedStyleAndLayoutDuration": 0,
"invoker": "DOMWindow.onclick",
"invokerType": "event-listener",
"name": "script",
"pauseDuration": 0,
"sourceURL": "https://web.dev/js/index-ffde4443.js",
"sourceFunctionName": "myClickHandler",
"sourceCharPosition": 17796,
"startTime": 11803.199999999255,
"window": [Window object],
"windowAttribution": "self"
}
],
"startTime": 11802.400000000373,
"styleAndLayoutStart": 11858.800000000745
}
همانطور که مشاهده می شود ، این مقدار بی سابقه ای از داده ها را برای وب سایت ها فراهم می کند تا بتوانند علت بروزرسانی های رندر لنگ را درک کنند.
از API قاب های انیمیشن طولانی در این زمینه استفاده کنید
ابزارهایی مانند Devtools Chrome و Lighthouse - در حالی که برای کشف و تولید مثل مسائل مفید هستند - ابزارهای آزمایشگاهی هستند که ممکن است جنبه های مهم تجربه کاربر را که فقط داده های میدانی می توانند از دست دهند ، از دست ندهند.
فریم های طولانی انیمیشن API به گونه ای طراحی شده است که در این زمینه برای جمع آوری داده های متنی مهم برای تعامل کاربر که API کارهای طولانی نمی تواند استفاده شود. این می تواند به شما در شناسایی و بازتولید موضوعات با تعامل که ممکن است در غیر این صورت کشف نکرده باشید ، کمک کند.
ویژگی تشخیص قاب های انیمیشن طولانی پشتیبانی API
در صورت پشتیبانی از API می توانید از کد زیر استفاده کنید تا آزمایش کنید:
if (PerformanceObserver.supportedEntryTypes.includes('long-animation-frame')) {
// Monitor LoAFs
}
پیوند به طولانی ترین تعامل INP
بارزترین مورد استفاده برای قاب های انیمیشن طولانی API کمک به تشخیص و رفع تعامل با مسائل بعدی رنگ (INP) است و این یکی از مهمترین دلایلی بود که تیم Chrome این API را توسعه داد. یک INP خوب جایی است که تمام تعامل ها در 200 میلی ثانیه یا کمتر از تعامل به آن پاسخ داده می شوند تا قاب رنگ نشود ، و از آنجا که قاب های انیمیشن طولانی API تمام قاب هایی را که 50 متر یا بیشتر طول می کشد اندازه گیری می کند ، بیشتر INP های مشکل ساز باید شامل داده های نان برای کمک به تشخیص شما در تشخیص شما باشند. آن تعامل
"LOAF INP" نان است که شامل تعامل INP است ، همانطور که در نمودار زیر نشان داده شده است:
در بعضی موارد امکان وجود یک رویداد INP وجود دارد - به طور معمول اگر تعامل پس از شروع قاب ، بخشی از قاب قبلی را آغاز کند ، و بنابراین کنترل کننده رویداد در قاب بعدی پردازش می شود:
حتی ممکن است که در برخی از شرایط نادر بیش از دو لنف باشد.
ضبط داده های LOAF (ها) مرتبط با تعامل INP به شما امکان می دهد تا اطلاعات بیشتری در مورد تعامل INP برای کمک به تشخیص آن کسب کنید. این امر به ویژه برای درک تأخیر ورودی مفید است: همانطور که می بینید اسکریپت های دیگر در آن قاب چه کار می کردند.
همچنین می توان برای درک مدت زمان پردازش غیر قابل توضیح و تأخیر در ارائه ، اگر دستگیرندگان رویداد شما در حال تولید مثل مقادیر دیده شده برای سایر اسکریپت ها برای کاربران شما در حال اجرا نباشند ، مفید باشد.
هیچ API مستقیمی برای پیوند ورود به INP با ورودی یا ورودی های مربوط به آن وجود ندارد ، اگرچه با مقایسه زمان شروع و پایان هر یک ، می توان این کار را به صورت کد انجام داد (به اسکریپت مثال WhyNP مراجعه کنید). کتابخانه web-vitals
شامل کلیه نان های متقاطع در ویژگی longAnimationFramesEntries
از رابط انتساب INP از V4 است.
پس از پیوند ورودی یا ورودی های Loaf ، می توانید اطلاعات را با انتساب INP درج کنید. شیء scripts
حاوی برخی از ارزشمندترین اطلاعات است زیرا می تواند نشان دهد که چه چیز دیگری در آن قاب ها اجرا می شود ، بنابراین اطلاعات را به سرویس تحلیلی شما باز می گرداند ، به شما امکان می دهد اطلاعات بیشتری در مورد دلیل کند بودن تعامل داشته باشید.
گزارش دادن نان برای تعامل INP یک روش مناسب برای یافتن آنچه مهمترین مشکلات تعامل در صفحه شماست است. هر کاربر ممکن است با صفحه شما متفاوت باشد و با حجم کافی از داده های انتساب INP ، تعدادی از موضوعات بالقوه در داده های انتساب INP گنجانده شود. این به شما امکان می دهد تا اسکریپت ها را بر اساس حجم مرتب کنید تا ببینید کدام اسکریپت ها با INP کند ارتباط دارند.
داده های انیمیشن طولانی تر را به نقطه پایانی تحلیلی گزارش دهید
نکته منفی که فقط به Loaf (های) INP نگاه می کنید ، این است که شما ممکن است مناطق بالقوه دیگری را برای پیشرفت هایی که ممکن است باعث ایجاد مشکلات بعدی INP شود ، از دست ندهید. این می تواند به احساس تعقیب دم شما منجر شود که در آن مسئله INP را برطرف می کنید و انتظار دارید پیشرفت بزرگی را مشاهده کنید ، فقط برای پیدا کردن کمترین تعامل بعدی فقط مقدار کمی بهتر از آن است بنابراین INP شما خیلی بهبود نمی یابد.
بنابراین به جای اینکه فقط به نان INP نگاه کنید ، ممکن است بخواهید همه نان های موجود در طول عمر صفحه را در نظر بگیرید:
با این حال ، هر ورودی نان حاوی داده های قابل توجهی است ، بنابراین شما احتمالاً می خواهید تجزیه و تحلیل خود را فقط به برخی از نان ها محدود کنید. علاوه بر این ، از آنجا که ورودی های قاب انیمیشن طولانی می توانند بسیار بزرگ باشند ، توسعه دهندگان باید تصمیم بگیرند که چه داده هایی از ورودی باید به تجزیه و تحلیل ارسال شود. به عنوان مثال ، زمان خلاصه ورود و شاید نام اسکریپت یا حداقل مجموعه ای از داده های متنی دیگر که ممکن است ضروری تلقی شوند.
برخی از الگوهای پیشنهادی برای کاهش میزان داده های قاب انیمیشن طولانی شامل موارد زیر است:
- قاب های انیمیشن طولانی را با تعامل مشاهده کنید
- قاب های انیمیشن طولانی را با مدت زمان مسدود کننده مشاهده کنید
- برای بهبود صافی ، قاب های انیمیشن طولانی را در حین به روزرسانی های مهم UI مشاهده کنید
- بدترین قاب های انیمیشن طولانی را مشاهده کنید
- الگوهای مشترک را در قاب های انیمیشن طولانی شناسایی کنید
کدام یک از این الگوهای برای شما بهتر عمل می کند ، بستگی به این دارد که در طول سفر بهینه سازی شما تا چه حد و فریم های انیمیشن طولانی چقدر مشترک هستند. برای سایتی که قبلاً هرگز برای پاسخگویی بهینه نشده است ، ممکن است بسیاری از نان ها وجود داشته باشد ، آیا ممکن است بخواهید فقط با تعامل با تعامل محدود کنید ، یا آستانه بالایی را تعیین کنید ، یا فقط به بدترین آنها نگاه کنید.
همانطور که مسائل پاسخگویی مشترک خود را برطرف می کنید ، ممکن است با محدود کردن فقط تعامل یا مدت زمان مسدود کننده یا با کاهش آستانه ها ، این مسئله را گسترش دهید.
قاب های انیمیشن طولانی را با تعامل مشاهده کنید
برای به دست آوردن بینش فراتر از قاب انیمیشن طولانی INP ، می توانید به تمام نان های تعامل (که می توان با حضور یک مقدار firstUIEventTimestamp
) با یک blockingDuration
بالا تشخیص داد ، نگاه کنید.
این همچنین می تواند به جای تلاش برای ارتباط این دو ، یک روش آسان تر برای نظارت بر نان های INP باشد ، که می تواند پیچیده تر باشد. در بیشتر موارد ، این شامل نان INP برای یک بازدید معین خواهد بود ، و در موارد نادری که هنوز هم باعث تعامل طولانی برای رفع آن نمی شود ، زیرا ممکن است تعامل INP برای سایر کاربران باشد.
کد زیر تمام ورودی های نان را با blockingDuration
بیشتر از 100 میلی ثانیه که در آن تعامل در طول قاب رخ داده است ، ثبت می کند. این 100 در اینجا انتخاب شده است زیرا کمتر از آستانه Inp "خوب" 200 میلی ثانیه است. بسته به نیاز خود می توانید مقدار بالاتر یا پایین تر را انتخاب کنید.
const REPORTING_THRESHOLD_MS = 100;
const observer = new PerformanceObserver(list => {
for (const entry of list.getEntries()) {
if (entry.blockingDuration > REPORTING_THRESHOLD_MS &&
entry.firstUIEventTimestamp > 0
) {
// Example here logs to console, but could also report back to analytics
console.log(entry);
}
}
});
observer.observe({ type: 'long-animation-frame', buffered: true });
قاب های انیمیشن طولانی را با مدت زمان مسدود کننده مشاهده کنید
به عنوان یک پیشرفت در نگاه کردن به تمام قاب های انیمیشن طولانی با تعامل ، ممکن است بخواهید به تمام قاب های انیمیشن طولانی با مدت زمان مسدود کننده نگاه کنید. اگر کاربر در این قاب های انیمیشن طولانی تعامل داشته باشد ، این مشکلات احتمالی INP را نشان می دهد.
کد زیر تمام ورودی های نان را با مدت زمان مسدود کردن بیشتر از 100 میلی ثانیه که در آن تعامل در طول قاب رخ داده است ، ثبت می کند. این 100 در اینجا انتخاب شده است زیرا کمتر از 200 میلی ثانیه "خوب" آستانه INP برای کمک به شناسایی فریم های مشکل احتمالی است ، در حالی که مقدار قاب های انیمیشن طولانی را به حداقل می رساند. بسته به نیاز خود می توانید مقدار بالاتر یا پایین تر را انتخاب کنید.
const REPORTING_THRESHOLD_MS = 100;
const observer = new PerformanceObserver(list => {
for (const entry of list.getEntries()) {
if (entry.blockingDuration > REPORTING_THRESHOLD_MS) {
// Example here logs to console, but could also report back to analytics
console.log(entry);
}
}
});
observer.observe({ type: 'long-animation-frame', buffered: true });
برای بهبود صافی ، قاب های انیمیشن طولانی را در حین به روزرسانی های مهم UI مشاهده کنید
همانطور که قبلاً ذکر شد ، با نگاهی به فریم های انیمیشن طولانی مدت مسدود کردن می توانند به پاسخگویی ورودی کمک کنند. اما برای صافی باید به تمام قاب های انیمیشن طولانی با duration
طولانی نگاه کنید.
از آنجا که ، این می تواند کاملاً پر سر و صدا شود ، ممکن است بخواهید اندازه گیری این موارد را به نقاط کلیدی با الگویی مانند این محدود کنید:
const REPORTING_THRESHOLD_MS = 100;
const observer = new PerformanceObserver(list => {
if (measureImportantUIupdate) {
for (const entry of list.getEntries()) {
if (entry.duration > REPORTING_THRESHOLD_MS) {
// Example here logs to console, but could also report back to analytics
console.log(entry);
}
}
}
});
observer.observe({ type: 'long-animation-frame', buffered: true });
async function doUIUpdatesWithMeasurements() {
measureImportantUIupdate = true;
await doUIUpdates();
measureImportantUIupdate = false;
}
بدترین قاب های انیمیشن طولانی را مشاهده کنید
به جای داشتن آستانه تعیین شده ، سایت ها ممکن است بخواهند داده ها را در طولانی ترین قاب انیمیشن (یا فریم) جمع آوری کنند تا حجم داده هایی را که باید به آنها دسترسی پیدا کنند ، کاهش دهند. بنابراین مهم نیست که چند قاب انیمیشن طولانی در یک صفحه تجربیات صفحه ، فقط داده ها برای بدترین حالت ، پنج ، ده یا با این وجود بسیاری از قاب های انیمیشن طولانی کاملاً ضروری است.
MAX_LOAFS_TO_CONSIDER = 10;
let longestBlockingLoAFs = [];
const observer = new PerformanceObserver(list => {
longestBlockingLoAFs = longestBlockingLoAFs.concat(list.getEntries()).sort(
(a, b) => b.blockingDuration - a.blockingDuration
).slice(0, MAX_LOAFS_TO_CONSIDER);
});
observer.observe({ type: 'long-animation-frame', buffered: true });
این استراتژی ها همچنین می توانند با هم ترکیب شوند - فقط به 10 بدترین نان ، با تعامل ، بیش از 100 میلی ثانیه نگاه کنید.
در زمان مناسب ( در حالت ایده آل در مورد رویداد visibilitychange
) Beacon به Analytics بازگشت. برای آزمایش محلی می توانید به صورت دوره ای console.table
استفاده کنید:
console.table(longestBlockingLoAFs);
الگوهای مشترک را در قاب های انیمیشن طولانی شناسایی کنید
یک استراتژی جایگزین این است که به اسکریپت های رایج که بیشترین ظاهر را در ورودی های قاب انیمیشن طولانی دارند ، نگاه کنیم. داده ها را می توان در یک اسکریپت و سطح موقعیت کاراکتر برای شناسایی مجرمان تکرار گزارش داد.
این ممکن است به ویژه برای سیستم عامل های قابل تنظیم که در آن مضامین یا افزونه هایی که باعث ایجاد مشکلات عملکرد می شوند در تعدادی از سایت ها شناسایی شوند.
زمان اجرای اسکریپت های مشترک-یا ریشه های شخص ثالث-در قاب های انیمیشن طولانی می تواند خلاصه شود و برای شناسایی مشارکت کنندگان مشترک در قاب های انیمیشن طولانی در یک سایت یا مجموعه ای از سایت ها گزارش شود. به عنوان مثال برای نگاه کردن به URL ها:
const observer = new PerformanceObserver(list => {
const allScripts = list.getEntries().flatMap(entry => entry.scripts);
const scriptSource = [...new Set(allScripts.map(script => script.sourceURL))];
const scriptsBySource= scriptSource.map(sourceURL => ([sourceURL,
allScripts.filter(script => script.sourceURL === sourceURL)
]));
const processedScripts = scriptsBySource.map(([sourceURL, scripts]) => ({
sourceURL,
count: scripts.length,
totalDuration: scripts.reduce((subtotal, script) => subtotal + script.duration, 0)
}));
processedScripts.sort((a, b) => b.totalDuration - a.totalDuration);
// Example here logs to console, but could also report back to analytics
console.table(processedScripts);
});
observer.observe({type: 'long-animation-frame', buffered: true});
و مثال این خروجی:
(index) | sourceURL | count | totalDuration |
---|---|---|---|
0 | 'https://example.consent.com/consent.js' | 1 | 840 |
1 | 'https://example.com/js/analytics.js' | 7 | 628 |
2 | 'https://example.chatapp.com/web-chat.js' | 1 | 5 |
از API قاب های انیمیشن طولانی در ابزار استفاده کنید
API همچنین به ابزار توسعه دهنده اضافی برای اشکال زدایی محلی اجازه می دهد. در حالی که برخی از ابزارها مانند Lighthouse و Chrome Devtools توانسته اند بخش اعظم این داده ها را با استفاده از جزئیات ردیابی سطح پایین جمع کنند ، داشتن این API سطح بالاتر می تواند به ابزارهای دیگر اجازه دسترسی به این داده ها را بدهد.
داده های انیمیشن طولانی سطح داده ها در devtools
شما می توانید قاب های انیمیشن طولانی را در DevTools با استفاده از API performance.measure()
که در آن نمایش داده می شود در ردیف های کاربر DevTools در آثار عملکردی نمایش دهید تا نشان دهد کجا می توانید تلاش های خود را برای پیشرفت عملکرد متمرکز کنید. با استفاده از API DevTools API ، این موارد حتی در مسیر خود نشان داده می شود:
const observer = new PerformanceObserver((list) => {
for (const entry of list.getEntries()) {
performance.measure('LoAF', {
start: entry.startTime,
end: entry.startTime + entry.duration,
detail: {
devtools: {
dataType: "track-entry",
track: "Long animation frames",
trackGroup: "Performance Timeline",
color: "tertiary-dark",
tooltipText: 'LoAF'
}
}
});
}
});
observer.observe({ type: 'long-animation-frame', buffered: true });
قاب های طولانی مدت ، قاب های انیمیشن طولانی احتمالاً در خود DevTools گنجانیده می شوند ، اما قطعه کد قبلی اجازه می دهد تا در این میان در آنجا ظاهر شود.
اولین ورود در شکل قبلی همچنین نشان می دهد که مرورگر چندین کار را با هم در همان قاب انیمیشن طولانی پردازش کرده است تا اینکه بین آنها ارائه شود. همانطور که قبلاً ذکر شد این ممکن است در شرایطی اتفاق بیفتد که هیچ کار ورودی با اولویت بالا وجود نداشته باشد ، اما صف کارها وجود دارد. اولین کار طولانی به روزرسانی های ارائه شده برای تکمیل (در غیر این صورت قاب انیمیشن طولانی فعلی پس از آن تنظیم می شود ، و یک کار جدید با کار بعدی شروع می شود) ، اما به جای اینکه فوراً آن را انجام دهید ، مرورگر تعدادی را پردازش کرده است وظایف اضافی و فقط پس از آن کار رندر طولانی را انجام داد و قاب انیمیشن طولانی را به پایان رساند. این نشان دهنده سودمندی نگاه کردن به قاب های انیمیشن طولانی در Devtools است نه فقط کارهای طولانی ، برای شناسایی رندرهای تأخیر.
از داده های قاب های انیمیشن طولانی در سایر ابزارهای توسعه دهنده استفاده کنید
اکنون همچنین داده های قاب انیمیشن طولانی را برای هر یک از پاسخ های INP و هر تعامل نشان می دهد:
از داده های قاب های انیمیشن طولانی در ابزارهای تست خودکار استفاده کنید
به طور مشابه ابزارهای تست خودکار در خطوط لوله CI/CD می توانند با اندازه گیری قاب های انیمیشن طولانی در حین اجرای مجموعه های مختلف تست ، جزئیات مربوط به عملکرد بالقوه را سطح بندی کنند.
سوالات متداول
برخی از سؤالات متداول در مورد این API عبارتند از:
چرا فقط در API کارهای طولانی گسترش یا تکرار نمی شود؟
این یک نگاه جایگزین برای گزارش یک اندازه گیری مشابه - اما در نهایت متفاوت - از موضوعات پاسخگویی بالقوه است. مهم است که سایتهای متکی به کارهای طولانی موجود API همچنان به عملکرد خود ادامه دهند تا از اختلال در موارد استفاده موجود جلوگیری کنند.
در حالی که API کارهای طولانی ممکن است از برخی از ویژگی های LOAF (مانند یک مدل انتساب بهتر) بهره مند شود ، ما معتقدیم که تمرکز روی فریم ها به جای کارها مزایای بسیاری را ارائه می دهد که این امر را به یک API اساساً متفاوت با API کارهای طولانی موجود تبدیل می کند.
چرا نوشته های اسکریپت ندارم؟
این ممکن است نشان دهد که قاب انیمیشن طولانی به دلیل Javascipt نیست ، بلکه در عوض به دلیل کار بزرگ ارائه شده است.
این همچنین می تواند زمانی اتفاق بیفتد که قاب انیمیشن طولانی به دلیل جاوا اسکریپت باشد اما جایی که نمی توان انتساب اسکریپت را به دلایل مختلف حریم خصوصی ارائه داد ، همانطور که قبلاً ذکر شد (در درجه اول که جاوا اسکریپت متعلق به صفحه نیست).
چرا ورودی های اسکریپت دارم اما اطلاعات منبع محدود یا محدود؟
این می تواند به دلایل مختلفی اتفاق بیفتد ، از جمله اینکه منبع خوبی برای اشاره به آن وجود ندارد .
اطلاعات اسکریپت همچنین برای اسکریپت های no-cors cross-origin
محدود خواهد بود ، اگرچه این کار را می توان با واگذاری آن اسکریپت ها با استفاده از COR با اضافه کردن crossOrigin = "anonymous"
به تماس <script>
حل کرد.
به عنوان مثال ، اسکریپت پیش فرض Google Tag Manager برای افزودن به صفحه:
<!-- Google Tag Manager -->
<script>(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
})(window,document,'script','dataLayer','GTM-XXXXXXX');</script>
<!-- End Google Tag Manager -->
می توان برای افزودن j.crossOrigin = "anonymous"
افزایش داد تا جزئیات کامل انتساب برای GTM ارائه شود
آیا این جایگزین API کارهای طولانی خواهد شد؟
در حالی که ما معتقدیم که قاب های انیمیشن طولانی API یک API بهتر و کامل تر برای اندازه گیری کارهای طولانی است ، در این زمان ، هیچ برنامه ای برای کاهش API کارهای طولانی وجود ندارد.
بازخورد می خواست
بازخورد را می توان در لیست مسائل GitHub ارائه داد ، یا اشکالات موجود در اجرای API Chrome را می توان در ردیاب شماره Chrome ثبت کرد.
نتیجه گیری
قاب های انیمیشن طولانی API یک API جدید هیجان انگیز با مزایای بالقوه زیادی نسبت به API کارهای طولانی قبلی است.
این ثابت است که ابزاری اصلی برای پرداختن به مسائل پاسخگویی است که توسط INP اندازه گیری می شود. INP یک متریک چالش برانگیز برای بهینه سازی است و این API یکی از راه هایی است که تیم Chrome به دنبال آن است تا شناسایی و پرداختن به مسائل را برای توسعه دهندگان آسانتر کند.
دامنه فریم های طولانی انیمیشن API فراتر از INP است ، و می تواند به شناسایی سایر دلایل به روزرسانی های آهسته کمک کند که می تواند بر هموار بودن کلی تجربه کاربر یک وب سایت تأثیر بگذارد.
قدردانی
تصویر تصویربرداری توسط هنری در Unsplash است.
،قاب های انیمیشن طولانی API (Loaf Proncted LO-AF) یک به روزرسانی در API کارهای طولانی است تا درک بهتری از به روزرسانی های آهسته رابط کاربری (UI) ارائه دهد. این می تواند برای شناسایی قاب های انیمیشن آهسته که احتمالاً بر تعامل با رنگ بعدی (INP) اصلی وب مهم تأثیر می گذارد ، مفید باشد که پاسخگویی را اندازه گیری می کند ، یا شناسایی سایر JANK UI که بر صافی تأثیر می گذارد.
وضعیت API
پس از یک آزمایش اصلی از Chrome 116 به Chrome 122 ، API LOAF از Chrome 123 ارسال شده است.
سابقه و هدف: API کارهای طولانی
قاب های انیمیشن طولانی API جایگزینی برای API کارهای طولانی است که مدتی در کروم در دسترس است (از زمان Chrome 58). همانطور که از نام آن پیداست ، API Task Long به شما امکان می دهد تا کارهای طولانی را کنترل کنید ، این وظایفی هستند که موضوع اصلی را برای 50 میلی ثانیه یا طولانی تر اشغال می کنند. وظایف طولانی را می توان با استفاده از رابط PerformanceLongTaskTiming
، با PeformanceObserver
کنترل کرد:
const observer = new PerformanceObserver((list) => {
console.log(list.getEntries());
});
observer.observe({ type: 'longtask', buffered: true });
کارهای طولانی به احتمال زیاد باعث ایجاد مشکلات پاسخگویی می شوند. اگر کاربر سعی می کند با یک صفحه تعامل داشته باشد - برای مثال ، روی یک دکمه کلیک کنید یا یک منو را باز کنید - اما موضوع اصلی در حال حاضر با یک کار طولانی روبرو است ، پس تعامل کاربر به تأخیر می افتد که منتظر تکمیل آن کار است.
برای بهبود پاسخگویی ، اغلب توصیه می شود کارهای طولانی را از بین ببرید . اگر در عوض هر کار طولانی به یک سری از کارهای متعدد و کوچکتر تقسیم شود ، ممکن است اجازه دهد کارهای مهمتر در بین آنها انجام شود تا از تأخیرهای قابل توجه در پاسخ به تعامل جلوگیری شود.
بنابراین هنگام تلاش برای بهبود پاسخگویی ، اولین تلاش اغلب برای انجام یک ردیابی عملکرد و نگاه کردن به کارهای طولانی است. این می تواند از طریق یک ابزار حسابرسی مبتنی بر آزمایشگاه مانند Lighthouse (که از حسابرسی کارهای طولانی مدت جلوگیری می کند ) یا با دیدن کارهای طولانی در Devtools Chrome .
آزمایش مبتنی بر آزمایشگاه اغلب یک مکان شروع ضعیف برای شناسایی مسائل پاسخگویی است ، زیرا این ابزارها ممکن است شامل تعامل نباشند-در صورت انجام ، آنها زیر مجموعه کوچکی از تعامل احتمالی هستند. در حالت ایده آل ، شما علل تعامل آهسته در این زمینه را اندازه گیری می کنید.
کاستی های API کارهای طولانی
اندازه گیری کارهای طولانی در این زمینه با استفاده از یک ناظر عملکرد فقط تا حدودی مفید است. در واقعیت ، اطلاعات زیادی را فراتر از این واقعیت نمی دهد که یک کار طولانی اتفاق افتاده است و چه مدت طول کشید.
ابزارهای نظارت واقعی کاربر (RUM) اغلب از این امر برای روند تعداد یا مدت زمان کارهای طولانی یا مشخص کردن صفحات در آنها استفاده می کنند - اما بدون جزئیات اساسی در مورد کار طولانی ، این فقط از کاربرد محدودی است. API کارهای طولانی فقط یک مدل انتساب اساسی دارد ، که در بهترین حالت فقط کانتینر را به شما می گوید که کار طولانی در (سند سطح بالا یا یک <iframe>
) اتفاق افتاده است ، اما اسکریپت یا عملکردی که آن را خوانده است ، همانطور که نشان داده شده است یک ورودی معمولی:
{
"name": "unknown",
"entryType": "longtask",
"startTime": 31.799999997019768,
"duration": 136,
"attribution": [
{
"name": "unknown",
"entryType": "taskattribution",
"startTime": 0,
"duration": 0,
"containerType": "window",
"containerSrc": "",
"containerId": "",
"containerName": ""
}
]
}
API کارهای طولانی نیز یک دیدگاه ناقص است ، زیرا ممکن است برخی از کارهای مهم را نیز حذف کند. برخی از به روزرسانی ها - مانند ارائه - در کارهای جداگانه ای که در حالت ایده آل باید همراه با اجرای قبلی باشد که باعث شده است که این بروزرسانی به طور دقیق "کار کل" برای آن تعامل را اندازه گیری کند ، قرار دهید. برای اطلاعات بیشتر در مورد محدودیت های تکیه بر کارها ، به بخش "جایی که کارهای طولانی کوتاه می آیند" از توضیح دهنده مراجعه کنید.
مسئله نهایی این است که اندازه گیری کارهای طولانی فقط در مورد کارهای فردی گزارش می شود که بیش از حد 50 میلی ثانیه طول می کشد. یک قاب انیمیشن می تواند از چندین کار کوچکتر از این حد 50 میلی ثانیه تشکیل شود ، اما در عین حال هنوز هم به طور جمعی توانایی ارائه مرورگر را مسدود می کند.
قاب های انیمیشن طولانی API
قاب های انیمیشن طولانی API (LOAF) یک API جدید است که به دنبال رفع برخی از کاستی های API کارهای طولانی است تا توسعه دهندگان بتوانند بینش های عملی تری کسب کنند تا به مشکلات پاسخگویی و بهبود INP کمک کنند ، و همچنین بینش در مورد مسائل مربوط به صافی کسب کنند. .
پاسخگویی خوب بدان معنی است که یک صفحه به سرعت به تعامل های ایجاد شده با آن پاسخ می دهد. این شامل قادر به نقاشی هرگونه به روزرسانی مورد نیاز کاربر به موقع و جلوگیری از جلوگیری از وقوع این به روزرسانی ها است. برای INP ، توصیه می شود در 200 میلی ثانیه یا کمتر پاسخ دهید ، اما برای سایر به روزرسانی ها (به عنوان مثال انیمیشن ها) حتی 200 میلی ثانیه ممکن است خیلی طولانی باشد.
قاب های انیمیشن طولانی API یک روش جایگزین برای اندازه گیری کار مسدود کننده است. به جای اندازه گیری وظایف فردی ، قاب های انیمیشن طولانی API - همانطور که نام آن پیداست - قاب های انیمیشن طولانی را اندازه گیری می کند. یک قاب انیمیشن طولانی زمانی است که یک به روزرسانی رندر فراتر از 50 میلی ثانیه به تأخیر می افتد (همان آستانه API کارهای طولانی).
قاب های انیمیشن طولانی از شروع کارهایی که به یک رندر نیاز دارند اندازه گیری می شوند. جایی که اولین کار در یک قاب انیمیشن بالقوه بالقوه نیازی به رندر ندارد ، قاب انیمیشن طولانی پس از اتمام کار غیر ارائه دهنده به پایان می رسد و یک قاب جدید انیمیشن طولانی بالقوه با کار بعدی آغاز می شود. چنین قاب انیمیشن طولانی غیر رندر هنوز هم در قاب های انیمیشن طولانی API گنجانده شده است که بیشتر از 50 میلی ثانیه (با زمان renderStart
0) برای اندازه گیری کار مسدود کننده بالقوه امکان پذیر است.
قاب های انیمیشن طولانی می توانند به روشی مشابه به عنوان کارهای طولانی با یک PerformanceObserver
مشاهده شوند ، اما به جای آن با نگاه به نوع long-animation-frame
نگاه می کنند:
const observer = new PerformanceObserver((list) => {
console.log(list.getEntries());
});
observer.observe({ type: 'long-animation-frame', buffered: true });
قاب های انیمیشن طولانی قبلی نیز می توانند از جدول زمانی عملکرد مانند SO پرسیده شوند:
const loafs = performance.getEntriesByType('long-animation-frame');
با این حال ، برای ورودی های عملکردی یک maxBufferSize
وجود دارد که پس از آن ورودی های جدیدتر از بین می روند ، بنابراین رویکرد PerformanceObServer رویکرد توصیه شده است. اندازه بافر long-animation-frame
بر روی 200 تنظیم شده است ، همانند long-tasks
.
مزایای نگاه به فریم به جای کارها
مزیت اصلی نگاه کردن به این موضوع از دیدگاه فریم و نه یک دیدگاه وظایف ، این است که یک انیمیشن طولانی می تواند از هر تعداد کارهایی که به صورت تجمعی منجر به یک قاب انیمیشن طولانی شده اند ، ساخته شود. این نکته نهایی را که قبلاً ذکر شد ، می پردازد ، جایی که جمع بسیاری از کارهای کوچکتر و مسدود کننده قبل از یک قاب انیمیشن ممکن است توسط API کارهای طولانی ظاهر نشود.
مزیت بیشتر این دیدگاه جایگزین در مورد کارهای طولانی ، امکان ارائه خرابی زمان بندی کل فریم است. Loaf به جای اینکه فقط یک startTime
و duration
، مانند API کارهای طولانی را شامل شود ، شامل یک تفکیک بسیار دقیق تر از قسمت های مختلف مدت قاب است.
زمان و مدت زمان بندی قاب
-
startTime
: زمان شروع قاب انیمیشن طولانی نسبت به زمان شروع ناوبری. -
duration
: مدت زمان قاب انیمیشن طولانی (شامل زمان ارائه نیست). -
renderStart
: زمان شروع چرخه ارائه ، که شامل درخواست هایrequestAnimationFrame
، محاسبه سبک و چیدمان ، تغییر اندازه ناظر و تقاطع ناظر است. -
styleAndLayoutStart
: آغاز دوره زمانی که در محاسبات سبک و چیدمان صرف شده است. -
firstUIEventTimestamp
: زمان اولین رویداد UI (ماوس/صفحه کلید و غیره) که در طول این قاب انجام می شود. -
blockingDuration
: مدت زمان کل در میلی ثانیه که قاب انیمیشن می تواند پردازش ورودی یا سایر کارهای با اولویت بالا را مسدود کند.
توضیح در مورد blockingDuration
یک قاب انیمیشن طولانی ممکن است از تعدادی از کارها ساخته شود. The blockingDuration
is the sum of task durations longer than 50 milliseconds (including the final render duration within the longest task).
For example, if a long animation frame was made up of two tasks of 55 milliseconds and 65 milliseconds followed by a render of 20 milliseconds, then the duration
would be approximately 140 milliseconds with a blockingDuration
of (55 - 50) + (65 + 20 - 50) = 40 milliseconds. For 40 milliseconds during this 140 millisecond long animation frame, the frame was considered blocked from handling input.
Whether to look at duration
or blockingDuration
For the common 60 hertz display, a browser will try to schedule a frame at least every 16.66 milliseconds (to ensure smooth updates), or after a high priority task like input handling (to ensure responsive updates). However, if there is no input—nor other high-priority tasks—but there is a queue of other tasks, the browser will typically continue the current frame well past 16.66 milliseconds no matter how well broken up the tasks are within it. That is, the browser will always try to prioritise inputs, but may choose to tackle a queue of tasks over render updates. This is due to rendering being an expensive process so processing a combined rendering task for multiple tasks usually leads to an overall reduction of work.
Therefore, long animation frames with a low or zero blockingDuration
should still feel responsive to input. Reducing or eliminating blockingDuration
by breaking up long tasks is therefore key to improving responsiveness as measured by INP.
However, a lot of long animation frames, regardless of blockingDuration
indicates UI updates that are delayed and so can still affect smoothness and lead to a feeling of a laggy user interface for scrolling or animations, even if these are less of an issue for responsiveness as measured by INP. To understand issues in this area look at the duration
, but these can be more tricky to optimize for since you cannot solve this by breaking up work, but instead must reduce work.
Frame timings
The previously mentioned timestamps allow the long animation frame to be divided into timings:
زمان بندی | محاسبه |
---|---|
زمان شروع | startTime |
زمان پایان | startTime + duration |
Work duration | renderStart ? renderStart - startTime : duration |
Render duration | renderStart ? (startTime + duration) - renderStart: 0 |
Render: Pre-layout duration | styleAndLayoutStart ? styleAndLayoutStart - renderStart : 0 |
Render: Style and Layout duration | styleAndLayoutStart ? (startTime + duration) - styleAndLayoutStart : 0 |
Better script attribution
The long-animation-frame
entry type includes better attribution data of each script that contributed to a long animation frame (for scripts longer than 5 milliseconds).
Similar to the Long Tasks API, this will be provided in an array of attribution entries, each of which details:
- A
name
andEntryType
both will returnscript
. - A meaningful
invoker
, indicating how the script was called (for example,'IMG#id.onload'
,'Window.requestAnimationFrame'
, or'Response.json.then'
). - The
invokerType
of the script entry point:-
user-callback
: A known callback registered from a web platform API (for example,setTimeout
,requestAnimationFrame
). -
event-listener
: A listener to a platform event (for example,click
,load
,keyup
). -
resolve-promise
: Handler of a platform promise (for example,fetch()
. Note that in the case of promises, all the handlers of the same promises are mixed together as one "script").
-
reject-promise
: As perresolve-promise
, but for the rejection. -
classic-script
: Script evaluation (for example,<script>
orimport()
) -
module-script
: Same asclassic-script
, but for module scripts.
-
- Separate timing data for that script:
-
startTime
: Time the entry function was invoked. -
duration
: The duration betweenstartTime
and when the subsequent microtask queue has finished processing. -
executionStart
: The time after compilation. -
forcedStyleAndLayoutDuration
: The total time spent processing forced layout and style inside this function (see thrashing ). -
pauseDuration
: Total time spent in "pausing" synchronous operations (alert, synchronous XHR).
-
- Script source details:
-
sourceURL
: The script resource name where available (or empty if not found). -
sourceFunctionName
: The script function name where available (or empty if not found). -
sourceCharPosition
: The script character position where available (or -1 if not found).
-
-
windowAttribution
: The container (the top-level document, or an<iframe>
) the long animation frame occurred in. -
window
: A reference to the same-origin window.
Where provided, the source entries allows developers to know exactly how each script in the long animation frame was called, down to the character position in the calling script. This gives the exact location in a JavaScript resource that resulted in the long animation frame.
Example of a long-animation-frame
performance entry
A complete long-animation-frame
performance entry example, containing a single script, is:
{
"blockingDuration": 0,
"duration": 60,
"entryType": "long-animation-frame",
"firstUIEventTimestamp": 11801.099999999627,
"name": "long-animation-frame",
"renderStart": 11858.800000000745,
"scripts": [
{
"duration": 45,
"entryType": "script",
"executionStart": 11803.199999999255,
"forcedStyleAndLayoutDuration": 0,
"invoker": "DOMWindow.onclick",
"invokerType": "event-listener",
"name": "script",
"pauseDuration": 0,
"sourceURL": "https://web.dev/js/index-ffde4443.js",
"sourceFunctionName": "myClickHandler",
"sourceCharPosition": 17796,
"startTime": 11803.199999999255,
"window": [Window object],
"windowAttribution": "self"
}
],
"startTime": 11802.400000000373,
"styleAndLayoutStart": 11858.800000000745
}
As can be seen, this gives an unprecedented amount of data for websites to be able to understand the cause of laggy rendering updates.
Use the Long Animation Frames API in the field
Tools like Chrome DevTools and Lighthouse—while useful for discovering and reproducing issues—are lab tools that may miss important aspects of the user experience that only field data can provide.
The Long Animation Frames API is designed to be used in the field to gather important contextual data for user interactions that the Long Tasks API couldn't. This can help you to identify and reproduce issues with interactivity that you might not have otherwise discovered.
Feature detecting Long Animation Frames API support
You can use the following code to test if the API is supported:
if (PerformanceObserver.supportedEntryTypes.includes('long-animation-frame')) {
// Monitor LoAFs
}
Link to the longest INP interaction
The most obvious use case for the Long Animation Frames API is to to help diagnose and fix Interaction to Next Paint (INP) issues, and that was one of the key reasons the Chrome team developed this API. A good INP is where all interactions are responded to in 200 milliseconds or less from interaction until the frame is painted, and since the Long Animation Frames API measures all frames that take 50ms or more, most problematic INPs should include LoAF data to help you diagnose those interactions.
The "INP LoAF" is the LoAF which includes the INP interaction, as shown in the following diagram:
In some cases it's possible for an INP event to span two LoAFs—typically if the interaction happens after the frame has started the rendering part of the previous frame, and so the event handler is processed in the next frame:
It's even possible that it may span more than two LoAFs in some rare circumstances.
Recording the LoAF(s) data associated with the INP interaction lets you to get much more information about the INP interaction to help diagnose it. This is particularly helpful to understand input delay : as you can see what other scripts were running in that frame.
It can also be helpful to understand unexplained processing duration and presentation delay if your event handlers are not reproducing the values seen for those as other scripts may be running for your users which may not be included in your own testing.
There is no direct API to link an INP entry with its related LoAF entry or entries , though it is possible to do so in code by comparing the start and end times of each (see the WhyNp example script ). The web-vitals
library includes all intersecting LoAFs in the longAnimationFramesEntries
property of the INP attribution interface from v4.
Once you have linked the LoAF entry or entries, you can include information with INP attribution. The scripts
object contains some of the most valuable information as it can show what else was running in those frames so beaconing back that data to your analytics service will allow you to understand more about why interactions were slow.
Reporting LoAFs for the INP interaction is a good way to find the what is the most pressing interactivity issues on your page. Each user may interact differently with your page and with enough volume of INP attribution data, a number of potential issues will be included in INP attribution data. This lets you to sort scripts by volume to see which scripts are correlating with slow INP.
Report more long animation data back to an analytics endpoint
One downside to only looking at the INP LoAF(s), is you may miss other potential areas for improvements that may cause future INP issues. This can lead to a feeling of chasing your tail where you fix an INP issue expecting to see a huge improvement, only to find the next slowest interaction is only a small amount better than that so your INP doesn't improve much.
So rather than only looking at the INP LoAF, you may want to consider all LoAFs across the page lifetime:
However, each LoAF entry contains considerable data, so you will likely want to restrict your analysis to only some LoAFs. Additionally, as the long animation frame entries can be quite large, developers should decide what data from the entry should be sent to analytics. For example, the summary times of the entry and perhaps the script names, or some other minimum set of other contextual data that may be deemed necessary.
Some suggested patterns to reduce the amount of long animation frame data includes:
- Observe long animation frames with interactions
- Observe long animation frames with high blocking durations
- Observe long animation frames during critical UI updates to improve smoothness
- Observe the worst long animation frames
- Identify common patterns in long animation frames
Which of these patterns works best for you, depends on how far along your optimization journey you are, and how common long animation frames are. For a site that has never optimized for responsiveness before, there may be many LoAFs do you may want to limit to just LoAFs with interactions, or set a high threshold, or only look at the worst ones.
As you resolve your common responsiveness issues, you may expand this by not limiting to just interactions or high blocking durations or by lowering thresholds.
Observe long animation frames with interactions
To gain insights beyond just the INP long animation frame, you can look at all LoAFs with interactions (which can be detected by the presence of a firstUIEventTimestamp
value) with a high blockingDuration
.
This can also be an easier method of monitoring INP LoAFs rather than trying to correlate the two, which can be more complex. In most cases this will include the INP LoAF for a given visit, and in rare cases when it doesn't it still surfaces long interactions that are important to fix, as they may be the INP interaction for other users.
The following code logs all LoAF entries with a blockingDuration
greater than 100 milliseconds where an interaction occurred during the frame. The 100 is chosen here because it is less than the 200 millisecond "good" INP threshold. You could choose a higher or lower value depending on your needs.
const REPORTING_THRESHOLD_MS = 100;
const observer = new PerformanceObserver(list => {
for (const entry of list.getEntries()) {
if (entry.blockingDuration > REPORTING_THRESHOLD_MS &&
entry.firstUIEventTimestamp > 0
) {
// Example here logs to console, but could also report back to analytics
console.log(entry);
}
}
});
observer.observe({ type: 'long-animation-frame', buffered: true });
Observe long animation frames with high blocking durations
As an improvement to looking at all long animation frames with interactions, you may want to look at all long animation frames with high blocking durations. These indicate potential INP problems if a user does interact during these long animation frames.
The following code logs all LoAF entries with a blocking duration greater than 100 milliseconds where an interaction occurred during the frame. The 100 is chosen here because it is less than the 200 millisecond "good" INP threshold to help identify potential problem frames, while keeping the amount of long animation frames reported to a minimum. You could choose a higher or lower value depending on your needs.
const REPORTING_THRESHOLD_MS = 100;
const observer = new PerformanceObserver(list => {
for (const entry of list.getEntries()) {
if (entry.blockingDuration > REPORTING_THRESHOLD_MS) {
// Example here logs to console, but could also report back to analytics
console.log(entry);
}
}
});
observer.observe({ type: 'long-animation-frame', buffered: true });
Observe long animation frames during critical UI updates to improve smoothness
As mentioned previously, looking at high blocking duration long animation frames can help to address input responsiveness. But for smoothness you should look at all long animation frames with a long duration
.
Since, this can get quite noisy you may want to restrict measurements of these to key points with a pattern like this:
const REPORTING_THRESHOLD_MS = 100;
const observer = new PerformanceObserver(list => {
if (measureImportantUIupdate) {
for (const entry of list.getEntries()) {
if (entry.duration > REPORTING_THRESHOLD_MS) {
// Example here logs to console, but could also report back to analytics
console.log(entry);
}
}
}
});
observer.observe({ type: 'long-animation-frame', buffered: true });
async function doUIUpdatesWithMeasurements() {
measureImportantUIupdate = true;
await doUIUpdates();
measureImportantUIupdate = false;
}
Observe the worst long animation frames
Rather than having a set threshold, sites may want to collect data on the longest animation frame (or frames), to reduce the volume of data that needs to be beaconed. So no matter how many long animation frames a page experiences, only data for the worst on, five, ten, or however many long animation frames absolutely necessary is beaconed back.
MAX_LOAFS_TO_CONSIDER = 10;
let longestBlockingLoAFs = [];
const observer = new PerformanceObserver(list => {
longestBlockingLoAFs = longestBlockingLoAFs.concat(list.getEntries()).sort(
(a, b) => b.blockingDuration - a.blockingDuration
).slice(0, MAX_LOAFS_TO_CONSIDER);
});
observer.observe({ type: 'long-animation-frame', buffered: true });
These strategies can also be combined—only look at the 10 worst LoAFs, with interactions, longer than 100 milliseconds.
At the appropriate time ( ideally on the visibilitychange
event ) beacon back to analytics. For local testing you can use console.table
periodically:
console.table(longestBlockingLoAFs);
Identify common patterns in long animation frames
An alternative strategy would be to look at common scripts appearing the most in long animation frame entries. Data could be reported back at a script and character position level to identify repeat offenders.
This may work particularly well for customizable platforms where themes or plugins causing performance issues could be identified across a number of sites.
The execution time of common scripts—or third-party origins—in long animation frames could be summed up and reported back to identify common contributors to long animation frames across a site or a collection of sites. For example to look at URLs:
const observer = new PerformanceObserver(list => {
const allScripts = list.getEntries().flatMap(entry => entry.scripts);
const scriptSource = [...new Set(allScripts.map(script => script.sourceURL))];
const scriptsBySource= scriptSource.map(sourceURL => ([sourceURL,
allScripts.filter(script => script.sourceURL === sourceURL)
]));
const processedScripts = scriptsBySource.map(([sourceURL, scripts]) => ({
sourceURL,
count: scripts.length,
totalDuration: scripts.reduce((subtotal, script) => subtotal + script.duration, 0)
}));
processedScripts.sort((a, b) => b.totalDuration - a.totalDuration);
// Example here logs to console, but could also report back to analytics
console.table(processedScripts);
});
observer.observe({type: 'long-animation-frame', buffered: true});
And example of this output is:
(index) | sourceURL | count | totalDuration |
---|---|---|---|
0 | 'https://example.consent.com/consent.js' | 1 | 840 |
1 | 'https://example.com/js/analytics.js' | 7 | 628 |
2 | 'https://example.chatapp.com/web-chat.js' | 1 | 5 |
Use the Long Animation Frames API in tooling
The API also allows additional developer tooling for local debugging. While some tooling like Lighthouse and Chrome DevTools have been able to gather much of this data using lower-level tracing details, having this higher-level API could allow other tools to access this data.
Surface long animation frames data in DevTools
You can surface long animation frames in DevTools using the performance.measure()
API, which are then displayed in the DevTools user timings track in performance traces to show where to focus your efforts for performance improvements. Using the DevTools Extensibility API these can even be shown in their own track:
const observer = new PerformanceObserver((list) => {
for (const entry of list.getEntries()) {
performance.measure('LoAF', {
start: entry.startTime,
end: entry.startTime + entry.duration,
detail: {
devtools: {
dataType: "track-entry",
track: "Long animation frames",
trackGroup: "Performance Timeline",
color: "tertiary-dark",
tooltipText: 'LoAF'
}
}
});
}
});
observer.observe({ type: 'long-animation-frame', buffered: true });
Longer term, long animation frames will likely be incorporated into DevTools itself, but the previous code snippet allows it to be surfaced there in the meantime.
The first entry in the previous figure also demonstrates where the browser has processed several tasks together in the same long animation frame rather than render between them. As mentioned previously this can happen when there are no high-priority input tasks, but there is a queue of tasks. The first long task has some render updates to complete (otherwise the current long animation frame would be reset after it, and a new one would start with the next task), but instead of actioning that render immediately, the browser has processed a number of additional tasks and only then actioned the long render task and ended the long animation frame. This demonstrates the usefulness of looking at long animation frames in DevTools, rather than just long tasks, to help identify delayed renders.
Use long animation frames data in other developer tooling
The Web Vitals extension has shown the value in logging summary debug information to diagnose performance issues.
It now also surfaces long animation frame data for each INP callback and each interaction:
Use long animation frames data in automated testing tools
Similarly automated testing tools in CI/CD pipelines can surface details on potential performance issues by measuring long animation frames while running various test suites.
سوالات متداول
Some of the frequently asked questions on this API include:
Why not just extend or iterate on the Long Tasks API?
This is an alternative look at reporting a similar—but ultimately different—measurement of potential responsiveness issues. It's important to ensure sites relying on the existing Long Tasks API continue to function to avoid disrupting existing use cases.
While the Long Tasks API may benefit from some of the features of LoAF (such as a better attribution model), we believe that focusing on frames rather than tasks offers many benefits that make this a fundamentally different API to the existing Long Tasks API.
Why do I not have script entries?
This may indicate that the long animation frame was not due to JavaScipt, but instead due to large render work.
This can also happen when the long animation frame is due to JavaScript but where the script attribution cannot be provided for various privacy reasons as noted previously (primarily that JavaScript not owned by the page).
Why do I have script entries but no, or limited, source information?
This can happen for a number of reasons, including there not being a good source to point to .
Script information will also be limited for no-cors cross-origin
scripts, though this can be resolved by fetching those scripts using CORS by adding crossOrigin = "anonymous"
to the <script>
call.
For example, the default Google Tag Manager script to add to the page:
<!-- Google Tag Manager -->
<script>(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
})(window,document,'script','dataLayer','GTM-XXXXXXX');</script>
<!-- End Google Tag Manager -->
Can be enhanced to add j.crossOrigin = "anonymous"
to allow full attribution details to be provided for GTM
Will this replace the Long Tasks API?
While we believe the Long Animation Frames API is a better, more complete API for measuring long tasks, at this time, there are no plans to deprecate the Long Tasks API.
Feedback wanted
Feedback can be provided at the GitHub Issues list , or bugs in Chrome's implementation of the API can be filed in Chrome's issue tracker .
نتیجه گیری
The Long Animation Frames API is an exciting new API with many potential advantages over the previous Long Tasks API.
It is proving to be a key tool for addressing responsiveness issues as measured by INP. INP is a challenging metric to optimize and this API is one way the Chrome team is seeking to make identifying and addressing issues easier for developers.
The scope of the Long Animation Frames API extends beyond just INP though, and it can help identify other causes of slow updates which can affect the overall smoothness of a website's user experience.