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

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

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

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

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

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

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

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

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

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

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

איסוף נתוני שדות באמצעות ספריית ה-JavaScript של web-vitals

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

תמיכה בדפדפן

  • 96
  • 96
  • x
  • x

מקור

ניתן להשתמש בגרסת ה-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. כאן נכנס לתמונה ה-build של השיוך (Attribution) של ספריית נכסי האינטרנט.

משפרים את הביצועים בעזרת גרסת ה-build של השיוך של ספריית אתרי האינטרנט

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

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

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

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

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

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

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

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

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

תמיכה בדפדפן

  • 123
  • 123
  • x
  • x

מקור

ניפוי באגים באינטראקציות באמצעות נתוני שטח הוא משימה מאתגרת. עם הנתונים מ-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 סוג החשבונית. יכול להיות 'user-callback', 'event-listener', 'resolve-promise', 'reject-promise', 'classic-script' או 'module-script'.
sourceURL כתובת ה-URL של הסקריפט שממנו הגיעה מסגרת האנימציה הארוכה.
sourceCharPosition מיקום התווים בסקריפט שזוהה על ידי sourceURL.
sourceFunctionName שם הפונקציה בסקריפט שזוהה.

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

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

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

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

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

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 הרשום שלו
  • קובץ הסקריפט – ומיקום התו בתוכו – מכילים את הקוד של הגורם המטפל באירועים הממושך.
  • השם של הפונקציה.

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

עיכובים בקלט ארוך

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

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

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

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

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

  // Get the longest script from the first LoAF entry:
  const loaf = attribution.longAnimationFrameEntries[0];
  const script = loaf?.scripts.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' היא שמשימת החסימה הייתה מעבודה אסינכרונית שהחלה קודם לכן, ושטופלה או נדחתה בפרק זמן שבו המשתמש ניסה ליצור אינטראקציה עם הדף, וכתוצאה מכך עכבה את האינטראקציה.

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

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

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

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

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

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

עיצוב ופריסה יקרים

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

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

requestAnimationFrame קריאות חוזרות (callback) מתמשכות

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

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

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

  // Get the longest script from the last LoAF entry:
  const loaf = attribution.longAnimationFrameEntries.at(-1);
  const script = loaf?.scripts.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, יש לוודא שהפעולה שאתם מבצעים בקריאות החוזרות (callback) הזו מוגבלת לביצוע העבודה שמובילה לעדכון בפועל של ממשק המשתמש. כל עבודה אחרת שלא תיגע ב-DOM או בסגנונות עדכון תעכב שלא לצורך את ציור הפריים הבא, לכן חשוב להיזהר!

סיכום

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

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