ממשק API למסגרות אנימציה ארוכות

Long Animation Frames API (לו-Af מבוטא LoAF) הוא עדכון ל-Long Tasks API שנועד לספק הבנה טובה יותר של עדכוני ממשק משתמש (UI) איטיים. האפשרות הזו יכולה להיות שימושית כדי לזהות פריימים של אנימציה איטית שעשויים להשפיע על מדד Interaction to Next Paint (INP) – מדד ליבה לבדיקת חוויית המשתמש באתר. המדד הזה מודד את הרספונסיביות, או כדי לזהות בעיות בממשק המשתמש שמשפיעות על החלקה.

סטטוס ה-API

תמיכה בדפדפן

  • Chrome: 123.
  • קצה: 123.
  • Firefox: לא נתמך.
  • Safari: לא נתמך.

מקור

בעקבות גרסת המקור לניסיון של Chrome 116 עד Chrome 122, ממשק LoAF API נשלח מ-Chrome 123.

רקע: Long Tasks API

תמיכה בדפדפן

  • Chrome: 58.
  • קצה: 79.
  • Firefox: לא נתמך.
  • Safari: לא נתמך.

מקור

ממשק ה-API של Long Animation Frames הוא חלופה ל-API של משימות ארוכות, שזמין ב-Chrome כבר זמן מה (החל מגרסה Chrome 58). כפי שמרמז על כך, ה-Long Task API מאפשר לכם לעקוב אחרי משימות ארוכות, שהן משימות שתופסות את ה-thread הראשי במשך 50 אלפיות השנייה או יותר. אפשר לעקוב אחרי משימות ארוכות בממשק PerformanceLongTaskTiming עם PeformanceObserver:

const observer = new PerformanceObserver((list) => {
  console.log(list.getEntries());
});

observer.observe({ type: 'longtask', buffered: true });

משימות ארוכות צפויות לגרום לבעיות של תגובה למשתמשים. אם משתמש מנסה לבצע אינטראקציה בדף – למשל ללחוץ על לחצן או לפתוח תפריט – אבל ה-thread הראשי כבר מטפל במשימה ארוכה, האינטראקציה של המשתמש מתעכבת בהמתנה עד שהמשימה תושלם.

כדי לשפר את הרספונסיביות, מומלץ בדרך כלל לפרק משימות ארוכות. אם כל משימה ארוכה מחולקת לסדרה של כמה משימות קטנות יותר, ייתכן שיהיה אפשר לבצע ביניהן משימות חשובות יותר כדי למנוע עיכובים משמעותיים בתגובה לאינטראקציות.

לכן, כשמנסים לשפר את הרספונסיביות, בדרך כלל המאמץ הראשון הוא להריץ מעקב ביצועים ולבדוק משימות ארוכות. אפשר לעשות את זה באמצעות כלי ביקורת מבוסס מעבדה כמו Lighthouse (שכולל ביקורת להימנע ממשימות ארוכות של שרשור ראשי), או לעיין במשימות ארוכות בכלי הפיתוח ל-Chrome.

בדיקות מבוססות-מעבדה בדרך כלל הן לא התחלה טובה לזיהוי בעיות רספונסיביות, כי הכלים האלה לא תמיד כוללים אינטראקציות. במקרים כאלה, מדובר רק בקבוצת משנה קטנה של אינטראקציות סבירות. מומלץ למדוד את הסיבות לאינטראקציות איטיות בשטח.

החסרונות של Long Tasks API

מדידה של משימות ארוכות בשטח באמצעות 'תצפית ביצועים' היא שימושית במידה מסוימת. בפועל, המידע לא מספק מידע רב מעבר לעובדה שמשימה ארוכה בוצעה ולמשך כמה זמן.

בדרך כלל, כלים של Real User Monitoring (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": ""
    }
  ]
}

גם ממשק ה-API של Tasks, לא הושלם, כי יכול להיות שהוא לא יכלול גם כמה משימות חשובות. עדכונים מסוימים, כמו רינדור, מתרחשים במשימות נפרדות, שרצוי לכלול יחד עם הביצוע הקודם, שגרם לעדכון הזה למדוד במדויק את 'העבודה הכוללת'. לאינטראקציה הזו. לפרטים נוספים על המגבלות של הסתמכות על משימות, אפשר לעיין במאמר איפה המשימות הארוכות מתקצרות בסעיף ההסבר.

הבעיה האחרונה היא שמדידת משימות ארוכות מדווחת רק על משימות נפרדות שנמשכות יותר מ-50 אלפיות השנייה. פריים של אנימציה יכול להיות מורכב מכמה משימות שקטנות מהמגבלה של 50 אלפיות השנייה, אבל בכל זאת לחסום את יכולת הדפדפן לבצע רינדור.

ממשק API למסגרות אנימציה ארוכות

תמיכה בדפדפן

  • Chrome: 123.
  • קצה: 123.
  • Firefox: לא נתמך.
  • Safari: לא נתמך.

מקור

Long Animation Frames API (LoAF) הוא ממשק API חדש שמטרתו לטפל בכמה מהחסרונות של Long Tasks API. בעזרת ה-API, המפתחים יכולים לקבל תובנות פרקטיות יותר שיעזרו לטפל בבעיות רספונסיביות ולשפר את ה-INP.

מהירות תגובה טובה פירושה שדף מגיב במהירות לאינטראקציות שבוצעו איתו. כדי לעשות את זה, צריכה להיות לכם אפשרות להציג את העדכונים שהמשתמשים צריכים לבצע בזמן, ומניעת החריגה מהעדכונים האלה. ב-INP מומלץ להגיב תוך 200 אלפיות השנייה, אבל בעדכונים אחרים (למשל, אנימציות) גם התגובה הזו עשויה להיות ארוכה מדי.

Long Animation Frames API הוא גישה חלופית למדידת עבודה חסומה. במקום למדוד את המשימות הנפרדות, ה-API של Long Animation Frames – כפי שמרמז השם שלו – מודד פריימים ארוכים של אנימציה. פריים אנימציה ארוך מופיע כשעדכון רינדור מתעכב יותר מ-50 אלפיות השנייה (זהו הסף לשימוש ב-Long Tasks API).

אפשר להבחין בפריימים ארוכים של אנימציה באותה דרך כמו משימות ארוכות עם 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, כמו ה-API של המשימות ארוכות, ב-LoAF יש פירוט הרבה יותר מפורט של החלקים השונים של משך הפריים, כולל:

  • startTime: שעת ההתחלה של מסגרת האנימציה הארוכה ביחס לשעת ההתחלה של הניווט.
  • duration: משך הזמן של מסגרת האנימציה הארוכה (לא כולל זמן ההצגה).
  • renderStart: שעת ההתחלה של מחזור הרינדור, שכוללת קריאות חוזרות (callback) של requestAnimationFrame, חישוב סגנון ופריסה, שינוי גודל של אובייקט צפייה וקריאה חוזרת (callbacks) של צופה בהצטלבות.
  • styleAndLayoutStart: תחילת התקופה של חישובי סגנון ופריסה.
  • firstUIEventTimestamp: השעה של האירוע הראשון בממשק המשתמש (עכבר/מקלדת וכו') לטיפול במהלך הפריים הזה.
  • blockingDuration: משך הזמן באלפיות השנייה שבו פריים האנימציה נחסם.

חותמות הזמן האלה מאפשרות לחלק את מסגרת האנימציה הארוכה לתזמונים:

תזמון החישוב
שעת ההתחלה startTime
שעת סיום startTime + duration
משך העבודה renderStart ? renderStart - startTime : duration
משך העיבוד renderStart ? (startTime + duration) - renderStart: 0
רינדור: משך הפריסה מראש styleAndLayoutStart ? styleAndLayoutStart - renderStart : 0
עיבוד: משך הזמן של הסגנון והפריסה styleAndLayoutStart ? (startTime + duration) - styleAndLayoutStart : 0

פרטים נוספים על התזמונים הנפרדים האלה זמינים במסמך ההסבר, שמספק פרטים מפורטים לגבי הפעילות שתורמת לפריים ארוך של אנימציה.

שיוך (Attribution) טוב יותר

סוג הרשומה long-animation-frame כולל נתוני שיוך (Attribution) טובים יותר לגבי כל סקריפט שתרמו לפריים של אנימציה ארוכה.

בדומה ל-Long Tasks API, המידע הזה יופיע במגוון רשומות שיוך, שכל אחת מהן כוללת את הפרטים:

  • גם name וגם EntryType יחזירו script.
  • invoker בעל משמעות שמציין איך הסקריפט נקרא (לדוגמה, 'IMG#id.onload', 'Window.requestAnimationFrame' או 'Response.json.then').
  • השדה invokerType של נקודת הכניסה לסקריפט:
    • user-callback: קריאה חוזרת (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: משך הזמן הכולל שהוקדש לעיבוד הפריסה והסגנון באילוץ של הפונקציה הזו (למידע נוסף על כיבוי).
    • 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 API בשדה

כלים כמו Chrome DevTools ו-Lighthouse – אמנם שימושיים לגילוי ולשחזור של בעיות – הם כלים לשיעור Lab שעלולים לפספס היבטים חשובים של חוויית המשתמש, שרק נתוני שטח יכולים לספק.

ה-API של מסגרת האנימציה הארוכה תוכנן לשימוש בשטח כדי לאסוף נתונים הקשריים חשובים לגבי אינטראקציות של משתמשים שלא הייתה אפשרות להשתמש בהן ב-Long Tasks API. כך תוכלו לזהות ולשחזר בעיות באינטראקטיביות, שיכול להיות שלא הייתם מגלים בדרך אחרת.

תמיכה בזיהוי תכונות ב-Long Animation Frames API

הקוד הבא יעזור לכם לבדוק אם ה-API נתמך:

if (PerformanceObserver.supportedEntryTypes.includes('long-animation-frame')) {
  // Monitor LoAFs
}

התרחיש לדוגמה הבולט ביותר של Long Animation Frames API הוא לעזור לאבחן ולפתור בעיות מסוג Interaction to Next Paint (INP). זו הייתה אחת מהסיבות העיקריות לכך שצוות Chrome פיתח את ה-API הזה. INP טוב הוא המקום שבו כל האינטראקציות מגיבות בתוך 200 אלפיות שנייה או פחות מהאינטראקציה, עד לציור הפריים.

ה-"INP LoAF" הוא LoAF שכולל את האינטראקציה של INP, כפי שמוצג בתרשים הבא:

דוגמאות למסגרות אנימציה ארוכות בדף, עם INP LoAF מודגש.
דף יכול לכלול הרבה הצהרות LoAF, שאחת מהן קשורה לאינטראקציה של INP.

במקרים מסוימים, יכול להיות שאירוע INP יתפרס על שתי בקשות LoAF – בדרך כלל אם האינטראקציה מתרחשת אחרי שהפריים התחיל את החלק של הרינדור של הפריים הקודם, ולכן הגורם המטפל באירועים שהוא עיבד במסגרת הבאה:

דוגמאות למסגרות אנימציה ארוכות בדף, עם INP LoAF מודגש.
דף יכול לכלול הרבה הצהרות LoAF, שאחת מהן קשורה לאינטראקציה של INP.

יכול להיות שהוא יתפרס על יותר משני אסימוני LoAF בנסיבות נדירות.

תיעוד הנתונים של LoAF המשויך לאינטראקציה של INP מאפשר לקבל מידע נוסף על האינטראקציה של INP כדי לעזור לאבחן אותה. האפשרות הזו שימושית במיוחד כדי להבין את עיכוב הקלט: אפשר לראות אילו סקריפטים אחרים פעלו במסגרת הזו.

כדאי גם להבין משך העיבוד ועיכוב במצגת לא מוסברים, אם הגורמים המטפלים באירועים לא משכפלים את הערכים שמוצגים עבור המשתמשים, כי יכול להיות שסקריפטים אחרים פועלים עבור המשתמשים, וייתכן שהם לא נכללים בבדיקות שלכם.

אין API ישיר שמאפשר לקשר רשומת INP לרשומה או לרשומות הקשורות ל-LoAF, למרות שניתן לעשות זאת בקוד על ידי השוואה בין זמני ההתחלה והסיום של כל אחד מהיעדים (יש לעיין בסקריפט לדוגמה של WhyNp).

הספרייה web-vitals כוללת את כל מזהי ה-LoAF שמצטלבים במאפיין longAnimationFramesEntries של ממשק השיוך (Attribution) של INP מגרסה 4.

אחרי שמקשרים את הרשומה או את הערכים של LoAF, אפשר לכלול מידע עם ייחוס INP. האובייקט scripts מכיל חלק מהמידע החשוב ביותר, כי הוא יכול להראות מה עוד פעלו במסגרות האלה. לכן, אם מחזירים את הנתונים האלה לשירות ניתוח הנתונים, תוכלו להבין טוב יותר למה האינטראקציות היו איטיות.

דיווח על שדות LoAF עבור האינטראקציה של INP הוא דרך טובה לזהות את בעיות האינטראקטיביות הדחופות ביותר בדף. לכל משתמש עשוי להיות אינטראקציה שונה עם הדף שלכם. כמו כן, אם יהיו מספיק נתוני שיוך של INP, נתוני השיוך (Attribution) של INP ייכללו במספר בעיות פוטנציאליות. כך ניתן למיין סקריפטים לפי נפח כדי לראות אילו סקריפטים קשורים ל-INP איטי.

דיווח על יותר נתוני אנימציה ארוכים לנקודת קצה של ניתוח נתונים

אחד החסרונות לבחינת רק את ה-INP LoAF הוא ייתכן שמפספסים תחומים פוטנציאליים אחרים לביצוע שיפורים שעשויים לגרום לבעיות INP עתידיות. כתוצאה מכך, תרגישו כאילו אתם רודפים אחרי הזנב ומתקנים בעיה שקשורה ל-INP בציפייה לשיפור משמעותי. רק כדי לגלות שהאינטראקציה הבאה האיטית ביותר תהיה טובה מעט מזו של ה-INP.

לכן, במקום להתמקד רק בהסתכלות על חוק ה-INP, כדאי לשקול את כל בקשות ה-LoAF לאורך משך החיים של הדף:

דף עם הרבה LoAF, חלקן מתרחשות במהלך אינטראקציות גם אם לא אינטראקציה עם INP.
בדיקה של כל ה-LoAF יכולה לעזור בזיהוי בעיות עתידיות ב-INP.

עם זאת, כל רשומה של LoAF מכילה נתונים רבים, כך שסביר להניח שלא תרצו לשווק את הכול בחזרה. במקום זאת, כדאי להגביל את הניתוח לחלק מה-LoAF או לנתונים מסוימים.

הנה כמה הצעות לדפוסים:

איזה מהדפוסים האלה הכי מתאים לכם, תלוי במרחק הדרך שלכם לאופטימיזציה ובאורך מסגרות האנימציה הנפוצות. באתר שלא עבר בעבר אופטימיזציה לתגובות, יכול להיות שיש הרבה מודעות LoAF שכדאי להגביל רק ל-LoAF עם אינטראקציות, להגדיר סף גבוה או לבדוק רק את הגרועות ביותר. במהלך פתרון הבעיות הנפוצות שקשורות לתגובות, אפשר להרחיב את השימוש בהן – לא להגביל רק אינטראקציות, להוריד ערכי סף או לחפש דפוסים מסוימים.

צפייה במסגרות אנימציה ארוכות עם אינטראקציות

כדי לקבל תובנות מעבר למסגרת האנימציה הארוכה של INP, אפשר לבחון את כל מודעות ה-LoAF עם אינטראקציות (שניתן לזהות באמצעות ערך של firstUIEventTimestamp).

זו גם יכולה להיות שיטה קלה יותר למעקב אחרי INP LoAF במקום לנסות למצוא קישור בין שני התחומים, דבר שיכול להיות מורכב יותר. ברוב המקרים הדוח יכלול את מספר ה-INP LoAF בביקור נתון. במקרים נדירים, האינטראקציות האלה עדיין מציגות אינטראקציות ארוכות שחשוב לתקן, כי זו עשויה להיות אינטראקציה עם INP עבור משתמשים אחרים.

הקוד הבא מתעד את כל רשומות LoAF במשך יותר מ-150 אלפיות השנייה שבהן התרחשה אינטראקציה במהלך הפריים. ה-150 נבחר כאן מפני שהוא מעט פחות מהטווח ה-'טוב' של 200 אלפיות השנייה סף INP. תוכלו לבחור ערך גבוה או נמוך יותר בהתאם לצרכים שלכם.

const REPORTING_THRESHOLD_MS = 150;

const observer = new PerformanceObserver(list => {
    for (const entry of list.getEntries()) {
      if (entry.duration > 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 והשדרים שמגיעים מסף מסוים בחזרה לנקודת קצה של Analytics לצורך ניתוח במועד מאוחר יותר:

const REPORTING_THRESHOLD_MS = 150;

const observer = new PerformanceObserver(list => {
  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 });

הרשומות של מסגרת האנימציה הארוכות יכולות להיות די גדולות, ולכן המפתחים צריכים להחליט אילו נתונים מהרשומה יישלחו לניתוח נתונים. לדוגמה, זמני הסיכום של הרשומה ואולי גם שמות הסקריפט, או קבוצה מינימלית אחרת של נתונים הקשריים אחרים שעשויים להיחשב כנחוצים.

צפייה במסגרות האנימציה הארוכות ביותר

במקום לקבוע סף מוגדר, יכול להיות שאתרים ירצו לאסוף נתונים במסגרת האנימציה הארוכה ביותר (פריימים) כדי לצמצם את נפח הנתונים שצריך לשייך אל הרשת. כך, לא משנה כמה זמן האנימציה מכילה את מספר הפריימים הגרועים ביותר של אנימציה בדף, רק הנתונים של האנימציה הגרועה ביותר, חמש או כל מסגרת האנימציה הארוכת ביותר שנדרשת בהחלט מועברות באמצעות משׂואת רשת (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 יחידות ה-LoAF הגרועות ביותר, עם אינטראקציות שנמשכות יותר מ-150 אלפיות השנייה.

בזמן המתאים (רצוי באירוע 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 ברמה גבוהה יותר הזה עשוי לאפשר לכלים אחרים לגשת לנתונים האלה.

הצגת נתונים של מסגרות אנימציה ארוכות בכלי הפיתוח

ניתן להציג פריימים ארוכים של אנימציה בכלי הפיתוח באמצעות ה-API performance.measure() שמוצג לאחר מכן במסלול תזמוני המשתמש של כלי הפיתוח בדוחות הביצועים, כדי להראות לכם איפה להתמקד כדי לשפר את הביצועים:

const observer = new PerformanceObserver((list) => {
  for (const entry of list.getEntries()) {
    performance.measure('LoAF', {
      start: entry.startTime,
      end: entry.startTime + entry.duration,
    });
  }
});

observer.observe({ type: 'long-animation-frame', buffered: true });

בטווח הארוך, סביר להניח שהוא ישולב בכלי הפיתוח עצמו, אבל קטע הקוד הקודם מאפשר להציג אותו שם בינתיים.

שימוש בנתונים של מסגרות אנימציה ארוכות בכלים אחרים למפתחים

התוסף Web Vitals הראה את הערך במידע על תוצאות ניפוי הבאגים של סיכום הרישום ביומן כדי לאבחן בעיות בביצועים.

עכשיו המערכת גם מציגה נתונים של פריימים ארוכים של אנימציה לכל קריאה חוזרת ל-INP ולכל אינטראקציה:

רישום ביומן במסוף התוספים של Web Vitals.
הרישום ביומן של מסוף Web Vitals במסוף שמופיע הוא נתוני LoAF.

שימוש בנתונים של מסגרות אנימציה ארוכות בכלי בדיקה אוטומטיים

באופן דומה, כלי בדיקה אוטומטיים בצינורות עיבוד נתונים של CI/CD יכולים לגלות פרטים על בעיות ביצועים פוטנציאליות על ידי מדידה של פריימים ארוכים של אנימציה בזמן הרצה של חבילות בדיקה שונות.

שאלות נפוצות

דוגמאות לשאלות נפוצות בנושא ה-API הזה:

למה לא רק להרחיב את היכולות של Long Tasks API או לחזור עליהן?

זו אפשרות חלופית לדיווח על מדידה דומה, אבל שונה, בסוף של בעיות פוטנציאליות של תגובה. חשוב לוודא שאתרים שמסתמכים על ממשק ה-API הקיים של Long Tasks ימשיכו לפעול כדי למנוע פגיעה בתרחישים לדוגמה קיימים.

אפשר להפיק תועלת מ-Long Tasks API מחלק מהתכונות של LoAF (כמו מודל שיוך טוב יותר), אבל אנחנו מאמינים שהתמקדות בפריימים במקום במשימות מעניקה הרבה יתרונות שהופכים את ה-API הזה לשונה לחלוטין מה-API הקיים של Long Tasks.

למה אין לי רשומות של סקריפטים?

הדבר עשוי להעיד על כך שמסגרת האנימציה הארוכה לא נבעה מ-JavaScipt אלא עקב עבודת רינדור גדולה.

מצב כזה יכול לקרות גם כשמסגרת האנימציה הארוכה כן בגלל JavaScript, אבל לא ניתן לספק את הייחוס של הסקריפט מסיבות שונות לשמירה על הפרטיות כפי שצוין קודם לכן (בעיקר JavaScript שלא נמצא בבעלות הדף).

למה יש לי רשומות של סקריפטים אבל לא מידע על מקור, או מידע מוגבל על מקור?

יכולות להיות לכך כמה סיבות, כולל המקור שאינו טוב להתייחס אליו.

גם פרטי הסקריפט יהיו מוגבלים ל-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" כדי לאפשר ציון של פרטי השיוך (Attribution) המלאים עבור GTM

האם הגרסה הזו תחליף את Long Tasks API?

אנחנו מאמינים ש-Long Animation Frames API הוא API טוב יותר ומלא יותר למדידת משימות ארוכות, בשלב זה, אנחנו לא מתכננים להוציא משימוש את Long Tasks API.

נשמח לקבל משוב

אפשר לשלוח משוב ברשימת הבעיות ב-GitHub. אפשר גם לדווח על באגים בהטמעה של ה-API ב-Chrome בכלי למעקב אחרי בעיות של Chrome.

סיכום

ממשק ה-API של Long Animation Frames הוא API חדש ומלהיב עם יתרונות פוטנציאליים רבים בהשוואה לממשק ה-API הקודם של Long Tasks.

הוא מוכיח את עצמו ככלי מרכזי לטיפול בבעיות רספונסיביות כפי שנמדד על ידי INP. INP הוא מדד מאתגר לביצוע אופטימיזציה. אחת הדרכים שבהן צוות Chrome מעוניין לעזור למפתחים לזהות בעיות ולטפל בהן.

עם זאת, ההיקף של Long Animation Frames API כולל מידע מעבר ל-INP, והוא יכול לעזור בזיהוי גורמים אחרים של עדכונים איטיים שיכולים להשפיע על יצירה חלקה של חוויית המשתמש באתר.

אישורים

תמונה ממוזערת שצולמה על ידי הנרי Be ב-Unbounce.