ניפוי באגים שינויים בפריסה

איך מזהים שינויים בפריסה ומתקנים אותם

Katie Hempenius
Katie Hempenius

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

כלים

Layout Instability API

Layout Instability API הוא המנגנון בדפדפן למדידת שינויים בפריסה ולדיווח עליהם. כל הכלים לניפוי באגים של שינויים בפריסה, כולל DevTools, מבוססים בסופו של דבר על Layout Instability API. עם זאת, השימוש ישירות ב-Layout Instability API הוא כלי ניפוי באגים חזק בזכות הגמישות שלו.

שימוש

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

let cls = 0;
new PerformanceObserver((entryList) => {
  for (const entry of entryList.getEntries()) {
    if (!entry.hadRecentInput) {
      cls += entry.value;
      console.log('Current CLS value:', cls, entry);
    }
  }
}).observe({type: 'layout-shift', buffered: true});

כשמריצים את הסקריפט הזה, חשוב לזכור:

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

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

LayoutShift

כל שינוי בפריסה מדווח באמצעות הממשק LayoutShift. התוכן של רשומה נראה כך:

duration: 0
entryType: "layout-shift"
hadRecentInput: false
lastInputTime: 0
name: ""
sources: (3) [LayoutShiftAttribution, LayoutShiftAttribution, LayoutShiftAttribution]
startTime: 11317.934999999125
value: 0.17508567530168798

הרשומה שלמעלה מציינת שינוי בפריסה במהלכו שלושה רכיבי DOM השתנו מיקום. הציון של שינוי הפריסה הזה היה 0.175.

אלה המאפיינים של מכונה של LayoutShift שרלוונטיים ביותר לניפוי באגים של שינויים בפריסה:

נכס תיאור
sources בנכס sources מפורטים רכיבי ה-DOM שהועברו במהלך שינוי הפריסה. המערך הזה יכול להכיל עד חמישה מקורות. אם יש יותר מחמישה רכיבים שמושפעים משינוי הפריסה, המערכת מדווחת על חמשת המקורות הגדולים ביותר (לפי ההשפעה על יציבות הפריסה) של שינוי הפריסה. המידע הזה מדווח באמצעות הממשק LayoutShiftAttribution (מפורט בהמשך).
value הנכס value מדווח על הציון של שינוי הפריסה של שינוי פריסה מסוים.
hadRecentInput המאפיין hadRecentInput מציין אם חל שינוי בפריסה תוך 500 אלפיות השנייה ממועד הקלט של המשתמש.
startTime המאפיין startTime מציין מתי התרחש שינוי בפריסת האתר. הערך של startTime מצוין באלפיות שנייה ונמדד ביחס לזמן שבו התחיל תהליך טעינת הדף.
duration המאפיין duration תמיד יוגדר כ-0. הנכס הזה עובר בירושה מהממשק PerformanceEntry (הממשק LayoutShift הוא הרחבה של הממשק PerformanceEntry). עם זאת, המושג 'משך זמן' לא חל על אירועי שינוי פריסה, ולכן הוא מוגדר כ-0. מידע על הממשק PerformanceEntry זמין במפרט.

LayoutShiftAttribution

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

לדוגמה, ה-JSON שבהמשך תואם לשינוי פריסה עם מקור אחד: השינוי כלפי מטה של רכיב ה-DOM <div id='banner'> מ-y: 76 ל-y:246.

// ...
  "sources": [
    {
      "node": "div#banner",
      "previousRect": {
        "x": 311,
        "y": 76,
        "width": 4,
        "height": 18,
        "top": 76,
        "right": 315,
        "bottom": 94,
        "left": 311
      },
      "currentRect": {
        "x": 311,
        "y": 246,
        "width": 4,
        "height": 18,
        "top": 246,
        "right": 315,
        "bottom": 264,
        "left": 311
      }
    }
  ]

המאפיין node מזהה את רכיב ה-HTML שהוזז. כשמעבירים את העכבר מעל המאפיין הזה ב-DevTools, רכיב הדף התואם מודגש.

המאפיינים previousRect ו-currentRect מדווחים על הגודל והמיקום של הצומת.

  • הקואורדינטות x ו-y מדווחות על קואורדינטת ה-x ועל קואורדינטת ה-y של הפינה הימנית העליונה של הרכיב, בהתאמה
  • המאפיינים width ו-height מדווחים על הרוחב והגובה של האלמנט, בהתאמה.
  • המאפיינים top, right, bottom ו-left מדווחים על ערכי הקואורדינטות x או y שתואמים לקצה הנתון של הרכיב. במילים אחרות, הערך של top שווה ל-y, והערך של bottom שווה ל-y+height.

אם כל המאפיינים של previousRect מוגדרים כ-0, המשמעות היא שהרכיב עבר לתצוגה. אם כל המאפיינים של currentRect מוגדרים ל-0, המשמעות היא שהרכיב השתנה מחוץ לתצוגה.

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

דוגמה מס' 1

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

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

דוגמה 2

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

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

דוגמה מס' 3

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

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

דוגמה 4

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

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

דוגמה לדיווח על שינויים ב-DOM באמצעות Layout Instability API

כלי פיתוח

חלונית הביצועים

בחלונית Experience (חוויית המשתמש) שבחלונית Performance (ביצועים) של DevTools מוצגים כל השינויים בפריסה שמתרחשים במהלך מעקב ביצועים נתון – גם אם הם מתרחשים תוך 500 אלפיות השנייה מממשק המשתמש, ולכן לא נספרים במדד CLS. אם מעבירים את העכבר מעל שינוי פריסה מסוים בחלונית חוויית השימוש, רכיב ה-DOM מושפע מודגש.

צילום מסך של שינוי פריסה שמוצג בחלונית &#39;רשת&#39; בכלי הפיתוח

כדי להציג מידע נוסף על שינויי הפריסה, לוחצים על שינויי הפריסה ואז פותחים את התיבה סיכום. שינויים במימדים של הרכיב מפורטים בפורמט [width, height], ושינויים במיקום של הרכיב מפורטים בפורמט [x,y]. המאפיין Had recent input מציין אם שינוי בפריסה התרחש תוך 500 אלפיות השנייה ממועד האינטראקציה של המשתמש.

צילום מסך של הכרטיסייה &#39;סיכום&#39; ב-DevTools לגבי שינוי פריסה

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

צילום מסך של הכרטיסייה &#39;יומן אירועים&#39; ב-DevTools לגבי שינוי פריסה

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

הדגשת האזורים שזזו בפריסה

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

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

תהליך החשיבה לזיהוי הסיבה לשינויים בפריסה

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

זיהוי הסיבה לשינוי בפריסה

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

  • שינויים במיקום של רכיב DOM
  • שינויים במאפיינים של רכיב DOM
  • הוספה או הסרה של רכיב DOM
  • אנימציות שמפעילות פריסה

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

  • האם המיקום או המימדים של הרכיב הקודם השתנו?
  • האם רכיב DOM הוכנס או הוסר לפני הרכיב שהוזז?
  • האם המיקום של הרכיב שהוזז השתנה באופן מפורש?

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

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

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

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

שינויים במיקום של רכיב (שאינם נובעים מהתנועה של רכיב אחר)

סוג השינוי הזה הוא בדרך כלל תוצאה של:

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

שינויים במאפייני המימדים של רכיב

סוג השינוי הזה הוא בדרך כלל תוצאה של:

  • גיליונות סגנונות שנטענים מאוחר או מחליפים סגנונות שהוגדרו בעבר.
  • תמונות ופריטי iframe ללא מאפייני width ו-height שנטענים אחרי שה'חריץ' שלהם עבר עיבוד.
  • בלוקים של טקסט ללא מאפייני width או height שמבצעים החלפה של גופנים אחרי שהטקסט עבר עיבוד.

הוספה או הסרה של רכיבי DOM

בדרך כלל, הסיבות לכך הן:

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

אנימציות שמפעילות פריסה

אפקטים מסוימים של אנימציה יכולים להפעיל את הפריסה. דוגמה נפוצה לכך היא כשרכיבי DOM 'מתנפשים' על ידי הגדלת מאפיינים כמו top או left, במקום להשתמש במאפיין transform של CSS. מידע נוסף זמין במאמר איך יוצרים אנימציות CSS עם ביצועים גבוהים.

איך משחזרים שינויי פריסה

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

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

new PerformanceObserver((entryList) => {
  for (const entry of entryList.getEntries()) {
    if (!entry.hadRecentInput) {
      cls += entry.value;
      debugger;
      console.log('Current CLS value:', cls, entry);
    }
  }
}).observe({type: 'layout-shift', buffered: true});

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