איך לזהות ולתקן שינויים בפריסה.
בחלק הראשון של המאמר נסביר על כלים לניפוי באגים של שינויים בפריסה, ובחלק השני נסביר על תהליך החשיבה שצריך להשתמש בו כדי לזהות את הסיבה לשינוי בפריסה.
כלים
Layout Instability API
Layout Instability API הוא המנגנון בדפדפן למדידת שינויים בפריסה ולדיווח עליהם. כל הכלים עבור שינויים בפריסת ניפוי באגים, כולל כלי פיתוח, מבוססים בסופו של דבר על ממשק API של 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
בהמתנה עד ה-thread לא פעיל כדי לדווח על שינויים בפריסה. כתוצאה מכך, בהתאם לאופן שבו ה-thread הראשי עמוס, יכול להיות שיהיה עיכוב קל בין המועד שבו הפריסה כאשר הוא נרשם במסוף. - הסקריפט הזה מתעלם משינויים בפריסה שהתרחשו תוך 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 שהשתנה. העברת העכבר מעליה
בנכס בכלי הפיתוח מודגש רכיב הדף המתאים.
המאפיינים previousRect
ו-currentRect
מדווחים על הגודל והמיקום של הצומת.
- הקואורדינטות
x
ו-y
מדווחות על קואורדינטת ה-x ועל קואורדינטת ה-y של הפינה הימנית העליונה של הרכיב, בהתאמה - המאפיינים
width
ו-height
מדווחים על הרוחב והגובה של האלמנט, בהתאמה. - הנכסים
top
,right
,bottom
ו-left
מדווחים על x או y לתאם ערכים שתואמים לקצה הנתון של הרכיב. בעוד במילים אחרות, הערך שלtop
שווה ל-y
; הערך שלbottom
שווה ל-y+height
אם כל המאפיינים של previousRect
מוגדרים כ-0, המשמעות היא שהרכיב
השתנה לתצוגה. אם כל המאפיינים של currentRect
מוגדרים כ-0, המשמעות היא
שהרכיב הועבר מהתצוגה.
אחד הדברים החשובים ביותר להבין כשמפרשים את הפלט הזה הוא שהרכיבים שמפורטים בתור מקורות הם הרכיבים שהשתנו במהלך השינוי של הפריסה. עם זאת, ייתכן שיסודות אלו באופן עקיף בלבד שקשורה ל'שורש הבעיה' של חוסר יציבות בפריסה. ריכזנו כאן כמה דוגמאות.
דוגמה ראשונה
שינוי הפריסה הזה ידווח עם מקור אחד: רכיב ב'. עם זאת, הסיבה העיקרית לשינוי הפריסה היא השינוי בגודל של רכיב א'.
דוגמה שנייה
בדוגמה הזו, השינוי בפריסה ידווח עם שני מקורות: רכיב א' ורכיב ב'. הגורם הבסיסי לשינוי הפריסה הזה הוא השינוי במיקום רכיב א'.
דוגמה 3
שינוי הפריסה בדוגמה הזו ידווח באמצעות מקור אחד: רכיב ב'. שינוי המיקום של רכיב ב' הוביל לשינוי הפריסה הזה.
דוגמה 4
למרות שרכיב ב' משנה את הגודל שלו, אין שינוי בפריסה בדוגמה הזו.
דוגמה לדיווח על שינויים ב-DOM באמצעות Layout Instability API
כלי פיתוח
חלונית הביצועים
בחלונית Experience שבחלונית Performance של DevTools מוצגים כל השינויים בפריסה שמתרחשים במהלך מעקב ביצועים נתון – גם אם הם מתרחשים תוך 500 אלפיות השנייה ממועד אינטראקציה של משתמש, ולכן לא נספרים במדד CLS. אם מעבירים את העכבר מעל שינוי פריסה מסוים בחלונית חוויית השימוש, רכיב ה-DOM מושפע מודגש.
כדי להציג מידע נוסף על שינויי הפריסה, לוחצים על שינויי הפריסה ואז פותחים את התצוגה הנפתחת סיכום. שינויים במימדים של הרכיב מפורטים בפורמט [width, height]
, ושינויים במיקום של הרכיב מפורטים בפורמט [x,y]
. המאפיין קיבלנו קלט לאחרונה מציין אם
שינוי הפריסה התרחש תוך 500 אלפיות השנייה מאינטראקציה של משתמש.
כדי לקבל מידע על משך השינוי של הפריסה, פותחים את הכרטיסייה יומן אירועים. אפשר גם לקבל הערכה לגבי משך הזמן של שינוי הפריסה על ידי בדיקת האורך של המלבן האדום של שינוי הפריסה בחלונית חוויית השימוש.
מידע נוסף על השימוש בחלונית ביצועים זמין בקטע ביצועים ניתוח חומר עזר.
הדגשת האזורים שזזו בפריסה
הדגשת אזורים לשינוי פריסה יכולה להיות שיטה שימושית לקבלת סקירה מהירה של המיקום והתזמון של שינויי הפריסה שמתרחש בדף.
כדי להפעיל את האפשרות 'אזורים בהיסט פריסה' בכלי פיתוח, עוברים אל הגדרות > כלים נוספים > רינדור > Layout Shift (אזורים) לאחר מכן רענן את הדף שברצונך לנפות בו באגים. אזורים שהפריסה שלהם השתנתה יסומנו למשך זמן קצר בצבע סגול.
תהליך החשיבה לזיהוי הסיבה לשינויים בפריסה
אפשר להשתמש בשלבים הבאים כדי לזהות את הגורם לשינויים בפריסה ללא קשר למועד או לאופן שבו מתרחש שינוי הפריסה. אפשר להוסיף לשלבים האלה את הפעלת Lighthouse. עם זאת, חשוב לזכור ש-Lighthouse יכול לזהות רק שינויים בפריסת הדף שהתרחשו במהלך טעינת הדף הראשונית. בנוסף, Lighthouse יכול לספק הצעות רק לגבי חלק מהסיבות לשינויים בפריסה – לדוגמה, רכיבי תמונה ללא רוחב ואורך מפורשים.
זיהוי הסיבה לשינוי בפריסה
האירועים הבאים יכולים לגרום לשינויים בפריסה:
- שינויים במיקום של רכיב DOM
- שינויים במאפיינים של רכיב DOM
- הזנה או הסרה של רכיב DOM
- אנימציות שמפעילות פריסה
באופן ספציפי, רכיב ה-DOM שמופיע מיד לפני הרכיב שעבר שינוי הוא הרכיב שסביר להניח שהוא 'גורם' לשינוי הפריסה. כך, כאשר כדי לבדוק את הסיבה לשינוי הפריסה, כדאי לשקול:
- האם המיקום או המימדים של הרכיב הקודם השתנו?
- האם רכיב DOM הוכנס או הוסר לפני הרכיב שהוזז?
- האם המיקום של הרכיב שהועבר השתנה באופן מפורש?
אם הרכיב הקודם לא גרם לשינוי הפריסה, ממשיכים לחפש רכיבים אחרים שקודמים לרכיב הזה או שנמצאים בסביבתו.
בנוסף, הכיוון והמרחק של שינוי הפריסה יכולים לספק רמזים על שורש הבעיה. לדוגמה, שינוי גדול כלפי מטה מצביע בדרך כלל על הוספת רכיב DOM, ואילו שינוי פריסה של פיקסל או 2 פיקסלים בדרך כלל מצביע על יישום של סגנונות CSS מתנגשים או טעינה ויישום של גופן Web.
אלה כמה מההתנהגויות הספציפיות שגורמות לאירועים של שינויים בפריסה בתדירות הגבוהה ביותר:
שינויים במיקום של רכיב (שאינם נובעים מהתנועה של רכיב אחר)
בדרך כלל, שינוי כזה נגרם כתוצאה מ:
- גיליונות סגנונות שנטענים מאוחר או מבטלים סגנונות שהוצהרו בעבר.
- אנימציות ואפקטים של מעבר.
שינויים במידות של רכיב
בדרך כלל, שינוי כזה נגרם כתוצאה מ:
- גיליונות סגנונות שנטענים מאוחר או מחליפים סגנונות שהוגדרו בעבר.
- תמונות ופריטי iframe ללא מאפייני
width
ו-height
שנטענים אחרי שה'חריץ' שלהם עבר עיבוד. - בלוקים של טקסט ללא המאפיינים
width
אוheight
שמחליפים גופנים אחרי הטקסט עבר עיבוד.
הוספה או הסרה של רכיבי DOM
פעמים רבות הסיבה לכך היא:
- הטמעת מודעות ופריטים מוטמעים אחרים של צד שלישי.
- הוספת באנרים, התראות ומודלים.
- גלילה מתמשכת ותבניות UX אחרות שטוענים תוכן נוסף למעלה תוכן קיים
אנימציות שמפעילות פריסה
אפקטים מסוימים של אנימציה יכולים להפעיל את הפריסה.
דוגמה לכך היא כשרכיבי DOM הם 'מונפשים' באמצעות הגדלת מספר הנכסים
כמו top
או left
במקום להשתמש בשירותים של CSS
transform
לנכס. מידע נוסף זמין במאמר איך יוצרים אנימציות CSS עם ביצועים גבוהים.
שחזור של שינויי הפריסה
אי אפשר לתקן שינויי פריסה שלא ניתן לשחזר. אחת הדרכים הפשוטות והיעילות ביותר להבין טוב יותר את יציבות הפריסה של האתר היא להקדיש 5-10 דקות לאינטראקציה עם האתר במטרה לגרום לשינויים בפריסה. חשוב להשאיר את המסוף פתוח בזמן ביצוע הפעולות האלה, ולהשתמש ב-Layout Instability API כדי לדווח על שינויים בפריסה.
אם קשה לאתר שינויים בפריסה, כדאי לחזור על התרגיל הזה במכשירים שונים ובמהירויות חיבור שונות. באופן ספציפי, שימוש
מהירות החיבור יכולה להקל על זיהוי שינויים בפריסה. In addition,
אפשר להשתמש בהצהרת 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 בשילוב עם כלי הרישום ביומן של הקצה הקדמי שבחרתם כדי לאסוף מידע נוסף על הבעיות האלה. ביצוע צ'ק-אאוט הקוד לדוגמה שמראה איך לעקוב אחר הרכיב הגדול ביותר שהשתנה בדף.