מדידת אינטראקציה עד הצבע הבא (INP)

1. מבוא

זהו Codelab אינטראקטיבי שבעזרתו אפשר ללמוד איך למדוד את Interaction to Next Paint (INP) באמצעות הספרייה web-vitals.

דרישות מוקדמות

מה תלמדו

  • איך להוסיף את הספרייה web-vitals לדף ולהשתמש בנתוני השיוך (Attribution) שלה.
  • בעזרת נתוני השיוך (Attribution) אפשר לאבחן איך להתחיל לשפר את INP ואיך להתחיל לשפר אותו.

מה צריך להכין

  • מחשב עם אפשרות לשכפל קוד מ-GitHub ולהריץ פקודות NPM.
  • כלי לעריכת טקסט.
  • גרסה עדכנית של Chrome כדי שכל המדידות של האינטראקציות יפעלו.

2. להגדרה

קבלת הקוד והפעלה שלו

הקוד נמצא במאגר web-vitals-codelabs.

  1. משכפלים את המאגר בטרמינל: git clone https://github.com/GoogleChromeLabs/web-vitals-codelabs.git.
  2. עוברים לספרייה המשוכפלת: cd web-vitals-codelabs/measuring-inp.
  3. יחסי תלות של התקנות: npm ci.
  4. מפעילים את שרת האינטרנט: npm run start.
  5. עוברים לכתובת http://localhost:8080/ בדפדפן.

כדאי לנסות את הדף

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

צילום מסך של דף ההדגמה של Gastropodicon

נסו לבצע פעולות בדף כדי להבין אילו אינטראקציות איטיות.

3. הגדרת המיקום בכלי הפיתוח ל-Chrome

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

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

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

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

4. בתהליך התקנה WebView

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

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

ה-Codelab הזה יתקין מ-npm ויטען את הסקריפט ישירות כדי להימנע מכניסה לתהליך build מסוים.

יש שתי גרסאות של web-vitals שאפשר להשתמש בהן:

  • העמודה "רגילה" כדאי להשתמש ב-build אם רוצים לעקוב אחרי ערכי המדדים של Core Web Vitals במהלך טעינת דף.
  • העמודה Attribution גרסת ה-build מוסיפה מידע על תוצאות ניפוי הבאגים לכל מדד כדי לאבחן למה מדד מסוים מסתיים בערך שלו.

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

כדי להוסיף את web-vitals אל devDependencies של הפרויקט, מריצים את npm install -D web-vitals

הוספת web-vitals לדף:

מוסיפים את גרסת השיוך של הסקריפט לתחתית הקובץ index.html ורושמים את התוצאות במסוף:

<script type="module">
  import {onINP} from './node_modules/web-vitals/dist/web-vitals.attribution.js';

  onINP(console.log);
</script>

רוצה לנסות?

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

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

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

כדאי לנסות להוסיף את האפשרות לסקריפט ולפעול שוב עם הדף:

<script type="module">
  import {onINP} from './node_modules/web-vitals/dist/web-vitals.attribution.js';

  onINP(console.log, {reportAllChanges: true});
</script>

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

צילום מסך של מסוף כלי הפיתוח עם הודעות INP שהודפסו בהצלחה

5. מה כלול בשיוך?

נתחיל באינטראקציה הראשונה של רוב המשתמשים עם הדף – תיבת הדו-שיח להבעת הסכמה לשימוש בקובצי cookie.

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

לוחצים על כן כדי לאשר קובצי Cookie (הדגמה) ובודקים את נתוני ה-INP שתועדו עכשיו במסוף כלי הפיתוח.

אובייקט הנתונים INP נרשם במסוף כלי הפיתוח

המידע ברמה העליונה הזה זמין גם בגרסה הרגילה וגם בגרסה של נכסי ה-VVR לשיוך:

{
  name: 'INP',
  value: 344,
  rating: 'needs-improvement',
  entries: [...],
  id: 'v4-1715732159298-8028729544485',
  navigationType: 'reload',
  attribution: {...},
}

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

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

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

attribution: {
  interactionTargetElement: Element,
  interactionTarget: '#confirm',
  interactionType: 'pointer',

  inputDelay: 27,
  processingDuration: 295.6,
  presentationDelay: 21.4,

  processedEventEntries: [...],
  longAnimationFrameEntries: [...],
}

קודם כל, יש מידע על התוכן שהייתה אינטראקציה איתו:

  • interactionTargetElement: הפניה פעילה לרכיב שהייתה לו אינטראקציה (אם הרכיב לא הוסר מה-DOM).
  • interactionTarget: בורר למציאת הרכיב בדף.

לאחר מכן, התזמון מתחלק באופן כללי:

  • inputDelay: הזמן שעבר מהרגע שהמשתמש התחיל את האינטראקציה (לדוגמה, לחץ על העכבר) ועד שההאזנה לאירוע של האינטראקציה הזו התחילה לפעול. במקרה הזה, השהיית הקלט הייתה רק כ-27 אלפיות השנייה, גם כשויסות הנתונים (throttle) במעבד (CPU) מופעל.
  • processingDuration: הזמן שלוקח ל-event listener לפעול להשלמת הפעולה. לעיתים קרובות, לדפים יהיו מספר מאזינים לאירוע יחיד (לדוגמה, pointerdown, pointerup ו-click). אם כל המודעות יופעלו באותה מסגרת אנימציה, הן ימוזגו בתקופה הזו. במקרה הזה, משך העיבוד נמשך 295.6 אלפיות השנייה – רוב זמן ה-INP.
  • presentationDelay: הזמן שעובר מהרגע שמאזינים לאירוע השלימו עד לזמן שבו הדפדפן מסיים לצבוע את הפריים הבא. במקרה הזה, 21.4 אלפיות השנייה.

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

יותר לעומק, processedEventEntries מכיל חמישה אירועים, בניגוד לאירוע היחיד במערך INP entries ברמה העליונה. מה ההבדל?

processedEventEntries: [
  {
    name: 'mouseover',
    entryType: 'event',
    startTime: 1801.6,
    duration: 344,
    processingStart: 1825.3,
    processingEnd: 1825.3,
    cancelable: true
  },
  {
    name: 'mousedown',
    entryType: 'event',
    startTime: 1801.6,
    duration: 344,
    processingStart: 1825.3,
    processingEnd: 1825.3,
    cancelable: true
  },
  {name: 'mousedown', ...},
  {name: 'mouseup', ...},
  {name: 'click', ...},
],

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

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

longAnimationFrameEntries

כשמרחיבים את הרשומה של LoAF:

longAnimationFrameEntries: [{
  name: 'long-animation-frame',
  startTime: 1823,
  duration: 319,

  renderStart: 2139.5,
  styleAndLayoutStart: 2139.7,
  firstUIEventTimestamp: 1801.6,
  blockingDuration: 268,

  scripts: [{...}]
}],

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

scripts: [{
  name: 'script',
  invoker: 'BUTTON#confirm.onclick',
  invokerType: 'event-listener',

  startTime: 1828.6,
  executionStart: 1828.6,
  duration: 294,

  sourceURL: 'http://localhost:8080/third-party/cmp.js',
  sourceFunctionName: '',
  sourceCharPosition: 1144
}]

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

טייק אוויי

מה אפשר לקבוע לגבי המקרה הזה על סמך נתוני השיוך (Attribution) האלה?

  • האינטראקציה הופעלה על ידי קליק על הרכיב button#confirm (מ-attribution.interactionTarget והמאפיין invoker ברשומת שיוך של סקריפט).
  • הזמן הושקע בעיקר בהפעלת פונקציות event listener (מ-attribution.processingDuration בהשוואה למדד הכולל value).
  • הקוד האיטי של event listener מתחיל מ-click listener שהוגדר ב-third-party/cmp.js (מ-scripts.sourceURL).

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

6. פונקציות event listener מרובות

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

מתחילים להקליד בתיבת החיפוש. מה רואים בנתוני השיוך? מה הבעיה לדעתך?

נתוני שיוך (Attribution)

ראשית, הנה סריקה כללית של דוגמה לבדיקת ההדגמה:

{
  name: 'INP',
  value: 1072,
  rating: 'poor',
  attribution: {
    interactionTargetElement: Element,
    interactionTarget: '#search-terms',
    interactionType: 'keyboard',

    inputDelay: 3.3,
    processingDuration: 1060.6,
    presentationDelay: 8.1,

    processedEventEntries: [...],
    longAnimationFrameEntries: [...],
  }
}

זהו ערך INP נמוך (עם ויסות נתונים במעבד (CPU)) מאינטראקציה במקלדת עם הרכיב input#search-terms. רוב הזמן (1,061 אלפיות השנייה) מתוך INP כולל של 1,072 אלפיות שנייה – הוקדש במשך העיבוד.

עם זאת, הערכים של scripts מעניינים יותר.

עומס רציף של פריסות

הרשומה הראשונה של המערך scripts נותנת לנו הקשר חשוב:

scripts: [{
  name: 'script',
  invoker: 'BUTTON#confirm.onclick',
  invokerType: 'event-listener',

  startTime: 4875.6,
  executionStart: 4875.6,
  duration: 497,
  forcedStyleAndLayoutDuration: 388,

  sourceURL: 'http://localhost:8080/js/index.js',
  sourceFunctionName: 'handleSearch',
  sourceCharPosition: 940
},
...]

רוב משך העיבוד מתרחש במהלך הפעלת הסקריפט הזו, שהיא האזנה מסוג input (ה-invoker הוא INPUT#search-terms.oninput). שם הפונקציה ניתן (handleSearch), כמו גם מיקום התווים בקובץ המקור index.js.

עם זאת, יש נכס חדש: forcedStyleAndLayoutDuration. זו הייתה הזמן שהוקדש להפעלת הסקריפט, שבה הדפדפן נאלץ להעביר מחדש את הדף. במילים אחרות, 78% מהזמן — 388 אלפיות שנייה מתוך 497 — נוצלו לביצוע האזנה לאירוע הזה, למעשה, בזבוז של הפריסה.

הבעיה הזו צריכה להיות בעדיפות עליונה לפתרון הבעיה.

מאזינים חוזרים

בנפרד, אין משהו ייחודי במיוחד בשני הערכים הבאים של הסקריפט:

scripts: [...,
{
  name: 'script',
  invoker: '#document.onkeyup',
  invokerType: 'event-listener',

  startTime: 5375.3,
  executionStart: 5375.3,
  duration: 124,

  sourceURL: 'http://localhost:8080/js/index.js',
  sourceFunctionName: '',
  sourceCharPosition: 1526,
},
{
  name: 'script',
  invoker: '#document.onkeyup',
  invokerType: 'event-listener',

  startTime: 5673.9,
  executionStart: 5673.9,
  duration: 95,

  sourceURL: 'http://localhost:8080/js/index.js',
  sourceFunctionName: '',
  sourceCharPosition: 1526
}]

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

מה מוזר ששניהם מגיעים מאותו קובץ מקור ואותו מיקום תווים.

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

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

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

7. השהיה לאחר קלט

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

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

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

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

לדוגמה, גם אם לא מפעילים פונקציות event listener אחרות — למשל על ידי לחיצה והתמקדות בתיבת החיפוש בדיוק כשהחילזון קופץ — פעולת ה-thread הראשי תגרום לדף לא להגיב למשך פרק זמן משמעותי.

דפים רבים לא יתנהגו כמו שצריך ב-thread הראשי, אבל זאת הדגמה טובה שמאפשרת לראות איך ניתן לזהות את ה-thread הזה בנתוני השיוך (Attribution) של INP.

הנה דוגמה לייחוס מהתמקדות בתיבת החיפוש רק במהלך עזיבה של שבלולים:

{
  name: 'INP',
  value: 728,
  rating: 'poor',

  attribution: {
    interactionTargetElement: Element,
    interactionTarget: '#search-terms',
    interactionType: 'pointer',

    inputDelay: 702.3,
    processingDuration: 4.9,
    presentationDelay: 20.8,

    longAnimationFrameEntries: [{
      name: 'long-animation-frame',
      startTime: 2064.8,
      duration: 790,

      renderStart: 2065,
      styleAndLayoutStart: 2854.2,
      firstUIEventTimestamp: 0,
      blockingDuration: 740,

      scripts: [{...}]
    }]
  }
}

כפי שתחזית, פונקציות event listener ביצעו במהירות – ראינו משך עיבוד של 4.9 אלפיות השנייה, והרוב המכריע של האינטראקציה הנמוכה היה השהיית קלט, כלומר 702.3 אלפיות השנייה מתוך 728 אלפיות שנייה.

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

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

scripts: [{
  name: 'script',
  invoker: 'SPAN.onanimationiteration',
  invokerType: 'event-listener',

  startTime: 2065,
  executionStart: 2065,
  duration: 788,

  sourceURL: 'http://localhost:8080/js/index.js',
  sourceFunctionName: 'cryptodaphneCoinHandler',
  sourceCharPosition: 1831
}]

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

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

8. השהיה של הצגת תגובה: כשאי אפשר להציג נתונים של עדכון

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

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

כיצד הכלי הזה נראה?

{
  name: 'INP',
  value: 376,
  rating: 'needs-improvement',
  delta: 352,

  attribution: {
    interactionTarget: '#sidenav-button>svg',
    interactionType: 'pointer',

    inputDelay: 12.8,
    processingDuration: 14.7,
    presentationDelay: 348.5,

    longAnimationFrameEntries: [{
      name: 'long-animation-frame',
      startTime: 651,
      duration: 365,

      renderStart: 673.2,
      styleAndLayoutStart: 1004.3,
      firstUIEventTimestamp: 138.6,
      blockingDuration: 315,

      scripts: [{...}]
    }]
  }
}

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

scripts: [{
  entryType: 'script',
  invoker: 'FrameRequestCallback',
  invokerType: 'user-callback',

  startTime: 673.8,
  executionStart: 673.8,
  duration: 330,

  sourceURL: 'http://localhost:8080/js/side-nav.js',
  sourceFunctionName: '',
  sourceCharPosition: 1193,
}]

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

9. סיכום

צבירת נתוני שדות

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

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

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

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

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

ייחוס בכל מקום!

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

עכשיו אפשר להשתמש בנתוני השיוך INP בכל אתר!

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

const script = document.createElement('script');
script.src = 'https://unpkg.com/web-vitals@4/dist/web-vitals.attribution.iife.js';
script.onload = function () {
  webVitals.onINP(console.log, {reportAllChanges: true});
};
document.head.appendChild(script);

מידע נוסף