ביצועי ניפוי באגים בשדה

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

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

  • כלי שיעור Lab: כלים כמו Lighthouse, שבהם הדף נטען סביבה מדומה שיכולה לחקות תנאים שונים (לדוגמה, ברשת ובמכשיר נייד פשוט).
  • כלי שדות: כלים כמו חוויית המשתמש ב-Chrome דיווח (CrUX), המבוסס על נתונים מצטברים של משתמשים אמיתיים מ-Chrome. (לתשומת ליבך נתוני שדות שמדווחים על ידי כלים כגון PageSpeed תובנות וחיפוש Google המקור של המסוף נתוני CrUX).

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

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

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

עולה שאלה חשובה: איך אפשר לתעד מידע על תוצאות ניפוי הבאגים מדדי ליבה לבדיקת חוויית המשתמש באתר או מדדי ביצועים אחרים ממשתמשים אמיתיים בשטח?

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

ממשקי API לשיוך ולניפוי באגים

Cumulative Layout Shift (CLS)

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

נבחן את הדוח הבא מ-PageSpeed Insights:

דוח PageSpeed Insights עם ערכי CLS שונים
PageSpeed Insights מציג נתוני שדות ונתוני Lab, אם הם זמינים, והם עשויים להיות שונים

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

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

קבלת ייחוס של שינוי פריסה

LayoutShiftAttribution הממשק נחשף בכל ערך layout-shift שחוסר יציבות הפריסה פולטים מ-API.

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

הנה קוד לדוגמה שמתעד כל שינוי פריסה וכן את הרכיבים שהשתנה:

new PerformanceObserver((list) => {
  for (const {value, startTime, sources} of list.getEntries()) {
    // Log the shift amount and other entry info.
    console.log('Layout shift:', {value, startTime});
    if (sources) {
      for (const {node, curRect, prevRect} of sources) {
        // Log the elements that shifted.
        console.log('  Shift source:', node, {curRect, prevRect});
      }
    }
  }
}).observe({type: 'layout-shift', buffered: true});

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

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

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

הקוד הבא מציג רשימה של layout-shift ערכים שתרמו ל-CLS ומחזירה את רכיב המקור הגדול ביותר מהשינוי הגדול ביותר:

function getCLSDebugTarget(entries) {
  const largestEntry = entries.reduce((a, b) => {
    return a && a.value > b.value ? a : b;
  });
  if (largestEntry && largestEntry.sources && largestEntry.sources.length) {
    const largestSource = largestEntry.sources.reduce((a, b) => {
      return a.node && a.previousRect.width * a.previousRect.height >
          b.previousRect.width * b.previousRect.height ? a : b;
    });
    if (largestSource) {
      return largestSource.node;
    }
  }
}

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

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

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

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

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

Largest Contentful Paint (LCP)

כדי לנפות באגים ב-LCP בשדה, המידע העיקרי שדרוש לכם הוא היה האלמנט הגדול ביותר (האלמנט מועמד ל-LCP) עבור אותו רכיב טעינת דף.

שימו לב שיכול להיות לגמרי – למעשה, די נפוץ – שמודל ה-LCP הרכיב המועמד יהיה שונה ממשתמש למשתמש, גם עבור אותו רכיב הדף הזה.

יכולות להיות לכך כמה סיבות:

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

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

זיהוי האלמנט של מועמד ל-LCP

כדי לקבוע את הרכיב האפשרי ל-LCP ב-JavaScript, אפשר להשתמש במאפיין הגדול ביותר Contentful Paint API, אותו API שבו משתמשים כדי לקבוע את ערך זמן ה-LCP.

במהלך תצפית על largest-contentful-paint רשומות, אפשר לקבוע אלמנט ה-LCP הנוכחי על ידי בדיקת המאפיין element של הרשומה האחרונה:

new PerformanceObserver((list) => {
  const entries = list.getEntries();
  const lastEntry = entries[entries.length - 1];

  console.log('LCP element:', lastEntry.element);
}).observe({type: 'largest-contentful-paint', buffered: true});

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

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

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

קטעי המידע שהכי חשוב לתעד בשדה INP הם:

  1. עם איזה רכיב הייתה אינטראקציה
  2. למה סוג האינטראקציה
  3. מתי התרחשה האינטראקציה?

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

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

הקוד הבא מתעד את רכיב היעד ואת הזמן של רשומת ה-INP.

function logINPDebugInfo(inpEntry) {
  console.log('INP target element:', inpEntry.target);
  console.log('INP interaction type:', inpEntry.name);
  console.log('INP time:', inpEntry.startTime);
}

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

שימוש עם ספריית ה-JavaScript של vitals

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

מגרסה 3, מדדי האתר ספריית JavaScript כוללת ייחוס לפתח מציגה את כל המידע הזה, וגם כמה תכונות נוספות אותות שונים.

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

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

function sendToGoogleAnalytics({name, value, id, attribution}) {
  const eventParams = {
    metric_value: value,
    metric_id: id,
  }

  switch (name) {
    case 'CLS':
      eventParams.debug_target = attribution.largestShiftTarget;
      break;
    case 'LCP':
      eventParams.debug_target = attribution.element;
      break;
    case 'INP':
      eventParams.debug_target = attribution.interactionTarget;
      break;
  }

  // Assumes the global `gtag()` function exists, see:
  // https://developers.google.com/analytics/devguides/collection/ga4
  gtag('event', name, eventParams);
}

onCLS(sendToGoogleAnalytics);
onLCP(sendToGoogleAnalytics);
onFID(sendToGoogleAnalytics);
onINP(sendToGoogleAnalytics);

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

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

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

גרסת ה-build של web-vitals חושפת נתוני שיוך נוספים, כפי שמוצג בדוגמה הבאה ל-INP:

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

function sendToGoogleAnalytics({name, value, id, attribution}) {
  const eventParams = {
    metric_value: value,
    metric_id: id,
  }

  switch (name) {
    case 'INP':
      eventParams.debug_target = attribution.interactionTarget;
      eventParams.debug_type = attribution.interactionType;
      eventParams.debug_time = attribution.interactionTime;
      eventParams.debug_load_state = attribution.loadState;
      eventParams.debug_interaction_delay = Math.round(attribution.inputDelay);
      eventParams.debug_processing_duration = Math.round(attribution.processingDuration);
      eventParams.debug_presentation_delay =  Math.round(attribution.presentationDelay);
      break;

    // Additional metric logic...
  }

  // Assumes the global `gtag()` function exists, see:
  // https://developers.google.com/analytics/devguides/collection/ga4
  gtag('event', name, eventParams);
}

onCLS(sendToGoogleAnalytics);
onLCP(sendToGoogleAnalytics);
onFID(sendToGoogleAnalytics);
onINP(sendToGoogleAnalytics);

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

דיווח על הנתונים והצגה חזותית שלהם

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

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

ל-GA4, אפשר לעיין במאמר הייעודי בנושא איך שולחים שאילתות לגבי הנתונים וממחישים אותם באמצעות ב-BigQuery.

סיכום

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

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

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

לבסוף, אם לדעתכם יש פערים ביכולת שלכם לנפות באגים במדדים האלה תכונות או מידע שחסרים בממשקי ה-API עצמם שולחים את המשוב web-vitals-feedback@googlegroups.com.