Long Animation Frames API (LoAF) هي تحديث لـ Long Tasks API لتقديم فهم أفضل لبطء تحديثات واجهة المستخدم. يمكن أن يكون ذلك مفيدًا لتحديد اللقطات البطيئة للرسوم المتحركة التي يُحتمل أن تؤثّر في مقياس مدى استجابة الصفحة لتفاعلات المستخدم (INP) ضمن "مؤشرات أداء الويب الأساسية" الذي يقيس مستوى الاستجابة، أو لتحديد أي مشاكل أخرى في واجهة المستخدم تؤثّر في سلاسة الأداء.
حالة واجهة برمجة التطبيقات
بعد فترة تجريبية للمصدر من Chrome 116 إلى Chrome 122، تم شحن LoAF API من Chrome 123.
الخلفية: واجهة Long Tasks API
واجهة برمجة التطبيقات Long Animation Frames API هي بديل لواجهة برمجة التطبيقات Long Tasks API التي كانت متاحة في Chrome منذ بعض الوقت (بدءًا من الإصدار 58). كما يوحي اسمها، تتيح لك Long Task API مراقبة المهام التي تستغرق وقتًا طويلاً، وهي المهام التي تشغل السلسلة الرئيسية لمدة 50 ملي ثانية أو أكثر. يمكن تتبُّع المهام الطويلة باستخدام واجهة PerformanceLongTaskTiming
من خلال PeformanceObserver
:
const observer = new PerformanceObserver((list) => {
console.log(list.getEntries());
});
observer.observe({ type: 'longtask', buffered: true });
من المرجح أن تتسبب المهام الطويلة في حدوث مشكلات في الاستجابة. إذا حاول أحد المستخدِمين التفاعل مع صفحة، مثلاً النقر على زر أو فتح قائمة، ولكنّ سلسلة المحادثات الرئيسية تتعامل حاليًا مع مهمة طويلة، يتأخّر تفاعل المستخدِم في انتظار إكمال هذه المهمة.
لتحسين وقت الاستجابة، يُنصح غالبًا بتقسيم المهام الطويلة. في حال تقسيم كل مهمة طويلة إلى سلسلة من المهام الأصغر حجمًا، قد يسمح ذلك بتنفيذ مهام أكثر أهمية بينها لتجنّب حدوث تأخيرات كبيرة في الاستجابة للتفاعلات.
لذلك عند محاولة تحسين سرعة الاستجابة، غالبًا ما يكون أول جهد هو إجراء تتبُّع الأداء والنظر في المهام الطويلة. ويمكن أن يكون ذلك من خلال أداة تدقيق معملية مثل Lighthouse (التي تحتوي على عملية تدقيق تجنّب المهام الطويلة في سلسلة التعليمات الرئيسية)، أو من خلال الاطّلاع على المهام الطويلة في "أدوات مطوري البرامج في Chrome".
غالبًا ما يكون الاختبار المستنِد إلى المختبر نقطة بداية سيئة لتحديد مشاكل الاستجابة، لأنّ هذه الأدوات قد لا تتضمّن التفاعلات، أو قد تتضمّن مجموعة فرعية صغيرة من التفاعلات المحتمَلة. من الناحية المثالية، ستقيس أسباب التفاعلات البطيئة في المجال.
أوجه القصور في Long Tasks API
إنّ قياس المهام الطويلة في الميدان باستخدام أداة "مراقبة الأداء" مفيد إلى حدّ ما فقط. في الواقع، لا تقدّم هذه الميزة الكثير من المعلومات سوى حقيقة حدوث مهمة طويلة ومدة استغراقها.
وغالبًا ما تستخدم أدوات "مراقبة المستخدمين" (RUM) هذه القيمة لمؤشر عدد المهام الطويلة أو مدتها أو لتحديد الصفحات التي تتم فيها، ولكن بدون التفاصيل الأساسية لسبب تنفيذ المهمة الطويلة، يمكن استخدام هذه الطريقة بشكل محدود فقط. تحتوي واجهة برمجة التطبيقات لمهام طويلة فقط على نموذج إحالة أساسي، والذي يطلعك في أحسن الأحوال على الحاوية التي حدثت فيها المهمة الطويلة (مستند المستوى الأعلى أو <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) هي واجهة برمجة تطبيقات جديدة تهدف إلى معالجة بعض أوجه القصور في Long Tasks API لتمكين المطوّرين من الحصول على إحصاءات أكثر فاعلية للمساعدة في معالجة مشاكل الاستجابة وتحسين INP، بالإضافة إلى الحصول على إحصاءات عن مشاكل السلاسة.
تعني الاستجابة الجيدة أنّ الصفحة تستجيب بسرعة للتفاعلات التي تتم معها. ويشمل ذلك إمكانية رسم أي تعديلات يحتاجها المستخدم في الوقت المناسب، وتجنُّب منع حدوث هذه التعديلات. بالنسبة إلى INP، ننصح بالردّ في غضون 200 ملي ثانية أو أقل، ولكن بالنسبة إلى التعديلات الأخرى (مثل الصور المتحركة)، قد تكون 200 ملي ثانية فترة طويلة جدًا.
وتُعد واجهة برمجة تطبيقات Long Animation Frames أسلوبًا بديلاً لقياس أعمال الحظر. بدلاً من قياس المهام الفردية، تقيس واجهة برمجة التطبيقات 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 مجموع العديد من المهام الأصغر حجمًا التي تمنع العرض قبل عرض إطار متحركة.
من المزايا الإضافية لهذا العرض البديل للمهام الطويلة هي إمكانية تقديم تفاصيل التوقيت للإطار بأكمله. بدلاً من تضمين startTime
وduration
فقط، مثل واجهة Long Tasks API، يتضمّن LoAF تحليلاً أكثر تفصيلاً للأجزاء المختلفة من مدة عرض اللقطة.
الطوابع الزمنية للإطارات ومدتها
-
startTime
: وقت بدء الصورة المتحركة التي تستغرق عرضها وقتًا طويلاً بالنسبة إلى وقت بدء التنقّل -
duration
: مدة عرض اللقطة الطويلة للحركة (باستثناء وقت العرض) -
renderStart
: وقت بدء دورة العرض، والذي يتضمّنrequestAnimationFrame
عمليات الاستدعاء وحساب التصميم والأسلوب وعمليات استدعاء مراقبي تغيير الحجم ومراقبي التقاطع styleAndLayoutStart
: بداية الفترة الزمنية التي يتم قضاؤها في عمليات احتساب الأنماط والتصميمات.-
firstUIEventTimestamp
: وقت أوّل حدث لواجهة المستخدم (الماوس/لوحة المفاتيح وما إلى ذلك) الذي يجب معالجته خلال هذا الإطار -
blockingDuration
: إجمالي المدة بالملي ثانية التي سيحظر فيها إطار الصورة المتحركة معالجة الإدخال أو المهام الأخرى ذات الأولوية العالية.
شرح حول blockingDuration
قد يتكون إطار الرسوم المتحركة الطويل من عدد من المهام. يمثّل blockingDuration
مجموع مدد المهام التي تزيد عن 50 ملي ثانية (بما في ذلك مدة العرض النهائي ضمن أطول مهمة).
على سبيل المثال، إذا كان إطارًا متحركة طويلاً يتألف من مهمتَين تستغرقان 55 مللي ثانية و65 مللي ثانية متبوعتين بعرض يستغرق 20 مللي ثانية، سيكون duration
140 مللي ثانية تقريبًا مع blockingDuration
ولمدة 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
: دالة استدعاء معروفة مسجّلة من واجهة برمجة تطبيقات لمنصّة الويب (مثل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
: إجمالي الوقت الذي تمّ إنفاقه في معالجة التنسيق والأسلوب الإجباريَين داخل هذه الدالة (راجِع الازدحام).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
}
يتضّح لنا هذا الأمر، ما يوفّر قدرًا غير مسبوق من البيانات للمواقع الإلكترونية التي يمكنها فهم سبب تأخُّر التعديلات في العرض.
استخدام واجهة برمجة تطبيقات Long Animation Frames في الحقل
على الرغم من أنّ أدوات مثل "أدوات مطوّري البرامج في Chrome" وLighthouse مفيدة لاكتشاف المشاكل وإعادة إنتاجها، إلا أنّها أدوات تجريبية قد لا ترصد جوانب مهمة من تجربة المستخدم لا يمكن توفيرها إلا من خلال البيانات الميدانية.
تم تصميم Long Animation Frames API لاستخدامها في المجال من أجل جمع البيانات السياقية المهمة لتفاعلات المستخدمين التي لا يمكن لواجهة برمجة التطبيقات Long Tasks API جمعها. ويمكن أن يساعدك ذلك في تحديد المشاكل المتعلّقة بالتفاعل وإعادة إنتاجها، والتي لم تكن لتتمكّن من اكتشافها بنفسك.
إتاحة استخدام Long Animation Frames API لميزة رصد المحتوى
يمكنك استخدام الرمز التالي لاختبار ما إذا كانت واجهة برمجة التطبيقات متوافقة:
if (PerformanceObserver.supportedEntryTypes.includes('long-animation-frame')) {
// Monitor LoAFs
}
رابط إلى أطول تفاعل INP
وتتمثل حالة الاستخدام الأكثر وضوحًا لواجهة برمجة تطبيقات Long Animation Frames API في المساعدة في تشخيص مشاكل مدى استجابة الصفحة لتفاعلات المستخدم (INP) وإصلاحها، وكان هذا أحد الأسباب الرئيسية لتطوير فريق Chrome لواجهة برمجة التطبيقات هذه. إنّ مدى استجابة الصفحة لتفاعلات المستخدم (INP) جيّد عندما يتم الردّ على كل التفاعلات خلال 200 ملّي ثانية أو أقلّ من التفاعل إلى أن يتم عرض الإطار. وبما أنّ واجهة برمجة تطبيقات Long Animation Frames API تقيس كل اللقطات التي تستغرق 50 ملّي ثانية أو أكثر، يجب أن تتضمّن معظم مقاييس INP المسببة مشاكل بيانات LoAF لمساعدتك في تشخيص تلك التفاعلات.
"مقياس استجابة الصفحة لتفاعلات المستخدم (INP) للصفحة المعروضة" هو مقياس استجابة الصفحة المعروضة الذي يتضمّن تفاعل INP، كما هو موضّح في المخطّط البياني التالي:
في بعض الحالات، يمكن أن يمتد حدث INP بين عمليتَي LoAF، عادةً إذا حدث التفاعل بعد أن يبدأ الإطار عرض جزء العرض من الإطار السابق، وبالتالي تتمّ معالجة معالِج الحدث في الإطار التالي:
ومن الممكن أن يشمل أكثر من اثنين من طلبات البحث ذات الصلة في بعض الحالات النادرة.
يتيح لك تسجيل بيانات LoAF المرتبطة بالتفاعل مع INP الحصول على مزيد من المعلومات عن التفاعل مع INP للمساعدة في تشخيصه. يساعد ذلك بشكل خاص في التعرّف على تأخّر الإدخال، لأنّه يمكنك التعرّف على النصوص البرمجية الأخرى التي كانت تعمل في هذا الإطار.
قد يكون من المفيد أيضًا فهم مدة المعالجة وتأخُّر العرض غير المُفترَضَين إذا كانت معالجات الأحداث لا تُعيد إنتاج القيم التي تظهر لهما، لأنّه قد يتم تشغيل نصوص برمجية أخرى للمستخدمين قد لا يتم تضمينها في اختباراتك.
لا تتوفّر واجهة برمجة تطبيقات مباشرة لربط إدخال INP بإدخالات LoAF ذات الصلة، ولكن يمكن إجراء ذلك في الرمز البرمجي من خلال مقارنة وقتَي البدء والانتهاء لكل إدخال (راجِع مثال النص البرمجي WhyNp). تتضمّن مكتبة web-vitals
كل إعلانات LoAF المتقاطعة في السمة longAnimationFramesEntries
الخاصة بواجهة تحديد المصدر INP من الإصدار 4.
بعد ربط إدخالات LoAF، يمكنك تضمين معلومات باستخدام الإسناد INP. يحتوي العنصر scripts
على بعض المعلومات الأكثر قيمة، إذ يمكنه عرض ما كان قيد التشغيل في تلك اللقطات، لذا فإنّ إعادة إرسال هذه البيانات إلى خدمة الإحصاءات تتيح لك فهم المزيد من المعلومات عن سبب بطء التفاعلات.
من خلال الإبلاغ عن "خيارات التفاعل مع الجمهور" بشأن مدى استجابة الصفحة لتفاعلات المستخدم (INP)، يمكنك معرفة المشاكل الأكثر إلحاحًا بشأن التفاعل على صفحتك. قد يتفاعل كلّ مستخدِم بشكلٍ مختلف مع صفحتك، ومع توفّر عدد كافٍ من بيانات تحديد المصدر بالاستناد إلى مصدر الإحالات الناجحة من الإنترنت، سيتمّ تضمين عدد من المشاكل المحتمَلة في بيانات تحديد المصدر بالاستناد إلى مصدر الإحالات الناجحة من الإنترنت. يتيح لك ذلك ترتيب النصوص البرمجية حسب وحدة التخزين لمعرفة النصوص البرمجية المرتبطة بمقياس INP البطيء.
الإبلاغ عن المزيد من بيانات الصور المتحركة الطويلة إلى نقطة نهاية إحصاءات
من بين الجوانب السلبية للاطّلاع على طلبات البحث التي لم تكتمل(LoAF) في "مدى استجابة الصفحة لتفاعلات المستخدم" فقط أنّك قد تفوتك مجالات أخرى محتملة للتحسينات التي قد تؤدي إلى حدوث مشاكل في "مدى استجابة الصفحة لتفاعلات المستخدم" في المستقبل. قد يؤدّي ذلك إلى شعور بالانزعاج عندما تحلّ مشكلة "مدى استجابة الصفحة لتفاعلات المستخدم" (INP) وتتوقّع أن تشهد تحسّنًا كبيرًا، لكنّ معرفة أبطأ تفاعل يكون أفضل بكثير من ذلك لكي لا يتحسن "مدى استجابة الصفحة لتفاعلات المستخدم" (INP) كثيرًا.
لذا، بدلاً من الاطّلاع على بيانات "وقت التحميل في وضع عدم الاتّصال بالإنترنت" (INP LoAF) فقط، ننصحك بالاطّلاع على جميع بيانات "وقت التحميل في وضع عدم الاتّصال بالإنترنت" على مدار عمر الصفحة:
ومع ذلك، يحتوي كل إدخال من خيارات LoAF على بيانات مهمة، لذا من المحتمل أن ترغب في قصر تحليلك على بعض خدمات LoAF فقط. بالإضافة إلى ذلك، بما أنّ إدخالات إطارات الرسوم المتحركة الطويلة يمكن أن تكون كبيرة جدًا، على المطوّرين تحديد البيانات التي يجب إرسالها من الإدخال إلى الإحصاءات. على سبيل المثال، أوقات ملخّص الإدخال وربما أسماء النصوص البرمجية، أو بعض الحد الأدنى من مجموعة البيانات السياقية الأخرى التي قد يُعتبَر أنّها ضرورية.
تشمل بعض الأنماط المقترَحة لتقليل مقدار بيانات إطارات الصور الطويلة للرسوم المتحركة ما يلي:
- مراقبة صور متحركة تستغرق وقتًا طويلاً مع التفاعلات
- مراقبة صور متحركة طويلة مع فترات حظر عالية
- مراقبة إطارات الصور المتحركة الطويلة أثناء تحديثات واجهة المستخدم المهمة لتحسين سلاسة الأداء
- تتبُّع أسوأ إطارات الصور المتحركة الطويلة
- تحديد الأنماط الشائعة في لقطات الرسوم المتحرّكة الطويلة
يعتمد النمط الأنسب لك على مدى تقدّمك في رحلة التحسين ومدى شيوع استخدام الإطارات الطويلة للرسوم المتحركة. بالنسبة إلى الموقع الإلكتروني الذي لم يتم تحسينه مطلقًا لتحسين وقت الاستجابة، قد يكون هناك العديد من عناصر LoAF التي قد تريد حصرها فقط بعناصر LoAF التي تتضمّن تفاعلات، أو ضبط حدّ أقصى مرتفع، أو الاطّلاع على العناصر الأسوأ فقط.
أثناء حلّ المشاكل الشائعة في وقت الاستجابة، يمكنك توسيع نطاق ذلك من خلال عدم الاقتصار على التفاعلات أو فترات الحظر الطويلة أو من خلال خفض الحدود الدنيا.
مراقبة صور متحركة طويلة مع التفاعلات
للحصول على إحصاءات تتعلّق بأكثر من إطار الرسوم المتحركة الطويلة في مقياس INP، يمكنك الاطّلاع على جميع إطارات الرسوم المتحركة الطويلة التي تتضمّن تفاعلات (يمكن رصدها من خلال توفّر قيمة firstUIEventTimestamp
) ذات قيمة blockingDuration
مرتفعة.
ويمكن أن تكون هذه الطريقة أسهل في تتبُّع طلبات البحث بدون موافقة INP بدلاً من محاولة الربط بينهما، الأمر الذي قد يكون أكثر تعقيدًا. في معظم الحالات، سيتضمّن ذلك "وقت الانتظار في الصفحة" لمسار الإحالة الناجحة (INP) لزيارة معيّنة، وفي الحالات النادرة التي لا يتضمّن فيها ذلك، سيظلّ يعرض التفاعلات الطويلة التي من المهم إصلاحها، لأنّها قد تكون تفاعل مسار الإحالة الناجحة (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 });
تتبُّع إطارات الصور المتحركة الطويلة التي تتضمن فترات حظر عالية
لتحسين النظر إلى جميع إطارات الرسوم المتحركة الطويلة ذات التفاعلات، قد تحتاج إلى إلقاء نظرة على جميع إطارات الرسوم المتحركة الطويلة ذات مدد الحظر العالية. تشير هذه القيم إلى مشاكل محتملة في سرعة الاستجابة للتفاعل إذا تفاعل المستخدم أثناء عرض هذه اللقطات الطويلة من الصور المتحركة.
يسجِّل الرمز التالي جميع إدخالات 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;
}
مراقبة أسوأ صور متحركة تستغرق وقتًا طويلاً
بدلاً من تحديد حدّ أدنى، قد تريد المواقع الإلكترونية جمع بيانات عن أطول إطار (أو إطارات) للحركة، وذلك لتقليل حجم البيانات التي يجب إرسالها إلى ال beacon. لذلك، بغض النظر عن عدد إطارات الصور المتحركة الطويلة التي تظهر في الصفحة، لا يتم إرسال سوى بيانات أسوأ إطار أو خمسة أو عشرة أو أي عدد ضروري من إطارات الصور المتحركة الطويلة.
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
)، تُرسِل الإشارة مرة أخرى إلى "إحصاءات Google". للاختبار على الجهاز، يمكنك استخدام 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 في الأدوات
تتيح واجهة برمجة التطبيقات أيضًا أدوات إضافية للمطوّرين لتصحيح الأخطاء على الجهاز. على الرغم من أنّ بعض الأدوات، مثل Lighthouse وChrome DevTools، تمكّنت من جمع الكثير من هذه البيانات باستخدام تفاصيل تتبُّع البيانات على مستوى أقل، فإنّ استخدام واجهة برمجة التطبيقات ذات المستوى الأعلى يمكن أن يسمح لأدوات أخرى بالوصول إلى هذه البيانات.
عرض بيانات صور متحركة تستغرق عرضها وقتًا طويلاً في "أدوات مطوّري البرامج"
يمكنك عرض لقطات متحركة طويلة في أدوات مطوّري البرامج باستخدام واجهة برمجة التطبيقات performance.measure()
، والتي يتم عرضها بعد ذلك في مسار توقيتات المستخدِم في أدوات مطوّري البرامج في عمليات تتبُّع الأداء لتحديد المواضع التي يجب التركيز فيها لتحسين الأداء. باستخدام 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، بدلاً من المهام الطويلة فقط، للمساعدة في تحديد عمليات التقديم المتأخرة.
استخدام بيانات إطارات الرسوم المتحركة الطويلة في أدوات المطوّرين الأخرى
أظهرت إضافة "مؤشرات أداء الويب" القيمة في معلومات تصحيح الأخطاء المرتبطة بملخّص التسجيل لتشخيص مشاكل الأداء.
ويعرِض الآن أيضًا بيانات إطارات الرسوم المتحركة الطويلة لكلّ مكالمة واردة من INP وكلّ تفاعل:
استخدام بيانات إطارات الرسوم المتحركة الطويلة في أدوات الاختبار الآلي
وبالمثل، يمكن لأدوات الاختبار المبرمَجة في مسارات التكامل المستمر/النشر الدائم عرض تفاصيل عن المشاكل المحتملة في الأداء من خلال قياس إطارات الصور الطويلة للرسوم المتحركة أثناء تشغيل مجموعات اختبارات مختلفة.
الأسئلة الشائعة
في ما يلي بعض الأسئلة الشائعة حول واجهة برمجة التطبيقات هذه:
لماذا لا يقتصر الأمر على توسيع واجهة برمجة تطبيقات Long Tasks API أو تكرارها فقط؟
يقدّم هذا التقرير قياسًا مشابهًا، ولكن مختلفًا في النهاية، لمشاكل الاستجابة المحتمَلة. من المهم التأكّد من استمرار عمل المواقع الإلكترونية التي تعتمد على واجهة Long Tasks API الحالية لتجنُّب إيقاف حالات الاستخدام الحالية.
على الرغم من أنّ Long Tasks API قد تستفيد من بعض ميزات LoAF (مثل نموذج تحديد مصدر أفضل)، نعتقد أنّ التركيز على اللقطات بدلاً من المهام يقدّم العديد من المزايا التي تجعل هذه الواجهة مختلفة بشكل أساسي عن Long Tasks API الحالية.
لماذا لا تتوفّر لدي إدخالات النص البرمجي؟
قد يشير ذلك إلى أنّ إطار الرسوم المتحركة الطويل لم يكن بسبب JavaScript، بل بسبب عمل كبير في المعالجة.
يمكن أن يحدث ذلك أيضًا عندما يكون إطار الصورة المتحرّكة الطويل ناتجًا عن JavaScript ولكن لا يمكن تقديم مصدر النص البرمجي لأسباب خصوصية مختلفة كما هو موضّح سابقًا (أهمّها أنّ JavaScript ليس ملكًا للصفحة).
لماذا تتوفّر لديّ إدخالات نصوص بدون معلومات مصدر أو مع معلومات محدودة؟
وقد يحدث ذلك لعدد من الأسباب، بما في ذلك عدم توفّر مصدر جيد للإشارة إليه.
ستكون معلومات النص البرمجي محدودة أيضًا في no-cors cross-origin
نصًا برمجيًا، على الرغم من إمكانية حل هذه المشكلة عن طريق استرجاع هذه النصوص البرمجية باستخدام سياسة مشاركة الموارد المتعددة المصادر (CORS) عن طريق إضافة crossOrigin = "anonymous"
إلى استدعاء <script>
.
على سبيل المثال، النص البرمجي التلقائي لخدمة "إدارة العلامات من Google" لإضافته إلى الصفحة:
<!-- 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"
للسماح بتقديم تفاصيل تحديد المصدر الكاملة لخدمة "إحصاءات Google 4".
هل ستحلّ هذه الواجهة محل Long Tasks API؟
على الرغم من أنّنا نعتقد أنّ Long Animation Frames API هي واجهة برمجة تطبيقات أفضل وأكمل لقياس المهام الطويلة، لا تتوفّر حاليًا أي خطط لإيقاف Long Tasks API نهائيًا.
نريد معرفة ملاحظاتك
يمكن تقديم الملاحظات في قائمة مشاكل GitHub، أو يمكن الإبلاغ عن الأخطاء في تنفيذ واجهة برمجة التطبيقات في Chrome في نظام تتبُّع المشاكل في Chrome.
الخاتمة
واجهة برمجة تطبيقات Long Animation Frames API هي واجهة برمجة تطبيقات جديدة ومثيرة للاهتمام بها العديد من المزايا المحتملة مقارنةً بواجهة برمجة تطبيقات Long Task API السابقة.
وتُثبت هذه الميزة أنّها أداة رئيسية لحلّ مشاكل الاستجابة كما يتم قياسها من خلال مقياس INP. ويشكّل INP مقياسًا صعبًا لتحسينه، وتمثّل واجهة برمجة التطبيقات هذه إحدى الطرق التي يسعى فريق Chrome إلى تسهيلها على المطوّرين لتحديد المشاكل ومعالجتها.
يتجاوز نطاق Long Animation Frames API مقياس INP، ويمكن أن يساعد في تحديد أسباب أخرى للتحديثات البطيئة التي يمكن أن تؤثّر في سلاسة تجربة المستخدم على الموقع الإلكتروني بشكل عام.