חיפוש אינטראקציות איטיות בשדה

איך למצוא אינטראקציות איטיות בנתוני השדה של האתר כדי לזהות הזדמנויות לשיפור המדד 'מאינטראקציה ועד הצגת התגובה'

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

במדריך הזה נסביר איך להעריך במהירות את ה-INP של האתר באמצעות נתוני שטח מדוח חוויית המשתמש ב-Chrome‏ (CrUX) כדי לראות אם יש באתר בעיות שקשורות ל-INP. לאחר מכן, תלמדו איך להשתמש ב-build של השיוך של ספריית ה-JavaScript של מדדי ה-Web Vitals – ואת התובנות החדשות שהיא מספקת מ-Long Animation Frames API‏ (LoAF) – כדי לאסוף ולפרש נתוני שדה של אינטראקציות איטיות באתר.

תחילה כדאי להשתמש ב-CrUX כדי להעריך את INP של האתר

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

נתוני CrUX מוצגים במספר תחומים שונים, והם תלויים בהיקף המידע שאתם מחפשים. מערכת CrUX יכולה לספק נתונים על INP ועל מדדים אחרים של Core Web Vitals לגבי:

  • דפים ספציפיים ומקורות שלמים באמצעות PageSpeed Insights.
  • סוגי דפים. לדוגמה, באתרי מסחר אלקטרוני רבים יש סוגים של דפי מוצר עם פרטים ודפי מוצר עם כרטיסי מוצר. אפשר לקבל נתוני CrUX לגבי סוגים ייחודיים של דפים ב-Search Console.

כנקודת התחלה, אפשר להזין את כתובת ה-URL של האתר ב-PageSpeed Insights. אחרי שמזינים את כתובת ה-URL, נתוני השדה שלה – אם הם זמינים – יוצגו במספר מדדים, כולל INP. אפשר גם להשתמש במתגי ההפעלה/השבתה כדי לבדוק את ערכי ה-INP של מאפיינים בניידים ובמחשבים.

נתוני שטח כפי שמוצגים על ידי CrUX ב-PageSpeed Insights, שכוללים את המדדים LCP,‏ INP ו-CLS כמדדי הליבה לבדיקת חוויית המשתמש באתר, את המדדים TTFB ו-FCP כמדדי אבחון ואת המדד FID כמדד של הליבה לבדיקת חוויית המשתמש באתר שהוצא משימוש.
תצוגה של נתוני CrUX כפי שהם מופיעים ב-PageSpeed Insights. בדוגמה הזו, ה-INP של דף האינטרנט הנתון זקוק לשיפור.

הנתונים האלה שימושיים כי הם מאפשרים לכם לדעת אם יש לכם בעיה. עם זאת, מה ש-CrUX לא יכול לעשות הוא לומר לך מה גורם לבעיות. יש הרבה פתרונות למעקב אחר משתמשים אמיתיים (RUM) שיעזרו לכם לאסוף נתוני שדה משלכם ממשתמשי האתר כדי לענות על השאלה הזו. אחת מהאפשרויות היא לאסוף את נתוני השדה האלה בעצמכם באמצעות ספריית JavaScript של מדדי ה-Web Vitals.

איסוף נתונים מהשטח באמצעות ספריית JavaScript‏ web-vitals

ספריית JavaScript‏ web-vitals היא סקריפט שאפשר לטעון באתר כדי לאסוף נתוני שדה ממשתמשי האתר. אפשר להשתמש בו כדי לתעד מספר מדדים, כולל INP בדפדפנים שתומכים בכך.

תמיכה בדפדפן

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

מקור

אפשר להשתמש בגרסה הרגילה של ה-build של ספריית מדדי הווידאו כדי לקבל נתוני INP בסיסיים ממשתמשים בשטח:

import {onINP} from 'web-vitals';

onINP(({name, value, rating}) => {
  console.log(name);    // 'INP'
  console.log(value);   // 512
  console.log(rating);  // 'poor'
});

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

import {onINP} from 'web-vitals';

onINP(({name, value, rating}) => {
  // Prepare JSON to be sent for collection. Note that
  // you can add anything else you'd want to collect here:
  const body = JSON.stringify({name, value, rating});

  // Use `sendBeacon` to send data to an analytics endpoint.
  // For Google Analytics, see https://github.com/GoogleChrome/web-vitals#send-the-results-to-google-analytics.
  navigator.sendBeacon('/analytics', body);
});

עם זאת, הנתונים האלה לבדם לא מספקים מידע משמעותי יותר מאשר דוח CrUX. כאן נכנסת לתמונה הגרסה של ספריית Web Vitals עם שיוך (Attribution).

שיפורים נוספים באמצעות גרסה של ספריית מדדי ה-Web Vitals עם שיוך

מודל השיוך (Attribution) של ספריית 'מדדי האתרים' מציג נתונים נוספים שאפשר לקבל ממשתמשים בשטח כדי לעזור לכם לפתור בעיות טובות יותר באינטראקציות בעייתיות שמשפיעות על ה-INP של האתר. אפשר לגשת לנתונים האלה דרך האובייקט attribution שמופיע בשיטה onINP() בספרייה:

import {onINP} from 'web-vitals/attribution';

onINP(({name, value, rating, attribution}) => {
  console.log(name);         // 'INP'
  console.log(value);        // 56
  console.log(rating);       // 'good'
  console.log(attribution);  // Attribution data object
});
איך יופיעו יומני המסוף מהספרייה של מדדי הליבה לבדיקת חוויית המשתמש באתר. במסוף שבדוגמאות האלה מוצגים שם המדד (INP), ערך ה-INP (56), המיקום של הערך הזה ביחס לסף ה-INP (טוב) וקטעי המידע השונים שמוצגים באובייקט השיוך, כולל רשומות מ-Long Animation Frames API.
איך נתונים מספריית vitals של דפי אינטרנט מופיעים במסוף.

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

  • "האם המשתמש יצר אינטראקציה עם הדף בזמן הטעינה שלו?"
  • "האם פונקציות הטיפול באירועים של האינטראקציה פעלו במשך זמן רב?"
  • "האם יש עיכוב בהפעלה של הקוד של אירוע האינטראקציה? אם כן, מה עוד קרה בשרשור הראשי באותו זמן?"
  • "האם האינטראקציה גרמה לעבודת עיבוד גרפי רבה שגרמה לעיכוב בהצגת הפריים הבא?"

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

מפתח אובייקט attribution נתונים
interactionTarget סלקטור CSS שמצביע על הרכיב שיצר את ערך ה-INP של הדף – לדוגמה, button#save.
interactionType סוג האינטראקציה, מקליקים, מקשקשות או מקלטות מקלדת.
inputDelay* ההשהיה בקלט של האינטראקציה.
processingDuration* הזמן שעובר מהרגע שבו ה-event listener הראשון התחיל לפעול בתגובה לאינטראקציה של המשתמש ועד לסיום העיבוד של כל ה-event listener.
presentationDelay* העיכוב בהצגה של האינטראקציה, שמתחיל מהרגע שבו הטיפול באירועים מסתיים ועד לרגע שבו התמונה הבאה נצבעת.
longAnimationFrameEntries* רשומות מ-LoAF שמשויכות לאינטראקציה. מידע נוסף זמין בקטע הבא.
*חדש בגרסה 4

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

Long Animation Frames API‏ (LoAF)

תמיכה בדפדפנים

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

מקור

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

גרסה build של השיוך בספריית מדדי ה-Web Vitals חושפת מערך של רשומות LoAF במפתח longAnimationFrameEntries של האובייקט attribution. בטבלה הבאה מפורטים כמה נתונים חשובים שאפשר למצוא בכל רשומה ב-LoAF:

מפתח אובייקט של רשומה ב-LoAF נתונים
duration משך הזמן של פריים האנימציה הארוך, עד לסיום הפריסה, לא כולל ציור ויצירת קומפוזיציה.
blockingDuration משך הזמן הכולל בפריים שבו הדפדפן לא הצליח להגיב במהירות בגלל משימות ארוכות. זמן החסימה הזה יכול לכלול משימות ארוכות שפועלות ב-JavaScript, וגם כל משימה ארוכה של עיבוד בפריים.
firstUIEventTimestamp חותמת הזמן של מועד ההוספה של האירוע לתור במהלך המסגרת. שימושי לזיהוי תחילת עיכוב הקלט של אינטראקציה.
startTime חותמת הזמן של תחילת המסגרת.
renderStart מתי התחילה עבודת הרינדור של המסגרת. הקריאות החוזרות האלה כוללות קריאות חוזרות של requestAnimationFrame (וקריאות חוזרות של ResizeObserver, אם רלוונטי), אבל יכול להיות שהן יתבצעו לפני תחילת העבודה על העיצוב או הפריסה.
styleAndLayoutStart כשמתבצעת עבודה על סגנון/פריסה בפריים. יכולה לעזור לכם להבין כמה זמן נדרשת עבודה על סגנון או על פריסה, כשאתם מביאים בחשבון חותמות זמן אחרות שזמינות.
scripts מערך פריטים שמכיל פרטי שיוך של סקריפט שתורמים ל-INP של הדף.
תצוגה חזותית של פריים ארוך של אנימציה לפי מודל LoAF.
תרשים של תזמון פריים ארוך של אנימציה לפי LoAF API (ללא blockingDuration).

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

מפתח אובייקט השיוך של הסקריפט נתונים
invoker מבצע ההפעלה. הערך הזה עשוי להשתנות בהתאם לסוג מבצע ההפעלה שמתואר בשורה הבאה. דוגמאות למפעילים יכולות להיות ערכים כמו 'IMG#id.onload',‏ 'Window.requestAnimationFrame' או 'Response.json.then'.
invokerType סוג ה-Invoker. יכול להיות 'user-callback', 'event-listener', 'resolve-promise', 'reject-promise', 'classic-script' או 'module-script'.
sourceURL כתובת ה-URL של הסקריפט שממנו הגיע פריים האנימציה הארוך.
sourceCharPosition מיקום התו בסקריפט שזוהה על ידי sourceURL.
sourceFunctionName שם הפונקציה בסקריפט שזוהה.

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

מדידה וזיהוי של סיבות נפוצות לאינטראקציות איטיות

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

עיבודים ארוכים

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

import {onINP} from 'web-vitals/attribution';

onINP(({name, value, attribution}) => {
  const {processingDuration} = attribution; // 512.5
});

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

import {onINP} from 'web-vitals/attribution';

onINP(({name, value, attribution}) => {
  const {processingDuration} = attribution; // 512.5

  // Get the longest script from LoAF covering `processingDuration`:
  const loaf = attribution.longAnimationFrameEntries.at(-1);
  const script = loaf?.scripts.sort((a, b) => b.duration - a.duration)[0];

  if (script) {
    // Get attribution for the long-running event handler:
    const {invokerType} = script;        // 'event-listener'
    const {invoker} = script;            // 'BUTTON#update.onclick'
    const {sourceURL} = script;          // 'https://example.com/app.js'
    const {sourceCharPosition} = script; // 83
    const {sourceFunctionName} = script; // 'update'
  }
});

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

  • הרכיב ו-event listener הרשום שלו.
  • קובץ הסקריפט – ומיקום התו בתוכו – שמכיל את הקוד של גורם הטיפול באירועים שפועל לאורך זמן.
  • שם הפונקציה.

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

עיכובים בהזנת קלט ארוך

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

import {onINP} from 'web-vitals/attribution';

onINP(({name, value, attribution}) => {
  const {inputDelay} = attribution; // 125.59439536
});

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

האם זה קרה במהלך טעינת הדף?

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

import {onINP} from 'web-vitals/attribution';

onINP(({name, value, attribution}) => {
  const {inputDelay} = attribution; // 125.59439536

  // Get the longest script from the first LoAF entry:
  const loaf = attribution.longAnimationFrameEntries[0];
  const script = loaf?.scripts.sort((a, b) => b.duration - a.duration)[0];

  if (script) {
    // Invoker types can describe if script eval blocked the main thread:
    const {invokerType} = script;    // 'classic-script' | 'module-script'
    const {sourceLocation} = script; // 'https://example.com/app.js'
  }
});

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

האם זה קרה אחרי טעינת הדף?

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

import {onINP} from 'web-vitals/attribution';

onINP(({name, value, attribution}) => {
  const {inputDelay} = attribution; // 125.59439536

  // Get the longest script from the first LoAF entry:
  const loaf = attribution.longAnimationFrameEntries[0];
  const script = loaf?.scripts.sort((a, b) => b.duration - a.duration)[0];

  if (script) {
    const {invokerType} = script;        // 'user-callback'
    const {sourceURL} = script;          // 'https://example.com/app.js'
    const {sourceCharPosition} = script; // 83
    const {sourceFunctionName} = script; // 'update'
  }
});

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

  • 'user-callback' מציין שהמשימה החוסמת הגיעה מ-setInterval, מ-setTimeout או אפילו מ-requestAnimationFrame.
  • הערך 'event-listener' מציין שהמשימה החוסמת הגיעה ממקור קלט קודם שהועמד בתור ועדיין נמצא בעיבוד.
  • הערכים 'resolve-promise' ו-'reject-promise' מציינים שהמשימה החוסמת הייתה חלק מעבודה אסינכררונית שהתחילה מוקדם יותר, והיא נפתרה או נדחתה בזמן שהמשתמש ניסה לבצע פעולה בדף, וכתוצאה מכך האינטראקציה התעכבה.

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

עיכובים ארוכים בהצגת התגובה

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

import {onINP} from 'web-vitals/attribution';

onINP(({name, value, attribution}) => {
  const {presentationDelay} = attribution; // 113.32307691
});

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

עבודות יקרות של עיצוב ופריסה

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

import {onINP} from 'web-vitals/attribution';

onINP(({name, value, attribution}) => {
  const {presentationDelay} = attribution; // 113.32307691

  // Get the longest script from the last LoAF entry:
  const loaf = attribution.longAnimationFrameEntries.at(-1);
  const script = loaf?.scripts.sort((a, b) => b.duration - a.duration)[0];

  // Get necessary timings:
  const {startTime} = loaf; // 2120.5
  const {duration} = loaf;  // 1002

  // Figure out the ending timestamp of the frame (approximate):
  const endTime = startTime + duration; // 3122.5

  // Get the start timestamp of the frame's style/layout work:
  const {styleAndLayoutStart} = loaf; // 3011.17692309

  // Calculate the total style/layout duration:
  const styleLayoutDuration = endTime - styleAndLayoutStart; // 111.32307691

  if (script) {
    // Get attribution for the event handler that triggered
    // the long-running style and layout operation:
    const {invokerType} = script;        // 'event-listener'
    const {invoker} = script;            // 'BUTTON#update.onclick'
    const {sourceURL} = script;          // 'https://example.com/app.js'
    const {sourceCharPosition} = script; // 83
    const {sourceFunctionName} = script; // 'update'
  }
});

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

קריאות חזרה ממושכות של requestAnimationFrame

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

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

onINP(({name, value, attribution}) => {
  const {presentationDelay} = attribution; // 543.1999999880791

  // Get the longest script from the last LoAF entry:
  const loaf = attribution.longAnimationFrameEntries.at(-1);
  const script = loaf?.scripts.sort((a, b) => b.duration - a.duration)[0];

  // Get the render start time and when style and layout began:
  const {renderStart} = loaf;         // 2489
  const {styleAndLayoutStart} = loaf; // 2989.5999999940395

  // Calculate the `requestAnimationFrame` callback's duration:
  const rafDuration = styleAndLayoutStart - renderStart; // 500.59999999403954

  if (script) {
    // Get attribution for the event handler that triggered
    // the long-running requestAnimationFrame callback:
    const {invokerType} = script;        // 'user-callback'
    const {invoker} = script;            // 'FrameRequestCallback'
    const {sourceURL} = script;          // 'https://example.com/app.js'
    const {sourceCharPosition} = script; // 83
    const {sourceFunctionName} = script; // 'update'
  }
});

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

סיכום

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

התמונה הראשית (Hero) מ-Unsplash, מאת Federico Respini.