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

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

תאריך פרסום: 11 במרץ 2021, תאריך עדכון אחרון: 7 בפברואר 2025

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

אפשר לנפות באגים של שינויים בפריסת הדף באמצעות Layout Instability API, או באמצעות כלים כמו DevTools שמסכמים נתונים מה-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

כלי פיתוח

ב-DevTools יש כמה כלים שיעזרו לכם לנפות באגים שקשורים לשינויים בפריסה.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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