איך לזהות ולתקן שינויים בפריסה.
החלק הראשון של המאמר הזה עוסק בכלים לניפוי באגים בשינויים בפריסה, והחלק השני עוסק בתהליך החשיבה שצריך להשתמש בו כדי לזהות את הסיבה לשינוי בפריסה.
כלים
API של אי יציבות בפריסה
ה-API של אי יציבות בפריסה הוא המנגנון של הדפדפן למדידה ולדיווח על שינויים בפריסה. כל הכלים לניפוי באגים בשינויים בפריסה, כולל כלי הפיתוח, מבוססים בסופו של דבר על ה-Layout Instability API. עם זאת, השימוש הישיר ב-Layout Instability API הוא כלי רב-עוצמה לניפוי באגים, הודות לגמישות שלו.
Usage
אפשר להשתמש בקטע קוד אחד שמודד 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
הרלוונטיים ביותר לניפוי באגים בשינויי פריסה:
מאפיין (property) | תיאור |
---|---|
sources |
הנכס sources מציג את רכיבי ה-DOM שהועברו בזמן שינוי הפריסה. מערך זה יכול להכיל עד חמישה מקורות. במקרה שיש יותר מחמישה רכיבים שמושפעים משינוי הפריסה, חמשת המקורות הגדולים ביותר (כפי שנמדדים על סמך ההשפעה על יציבות הפריסה) מדווחים. המידע הזה מדווח באמצעות הממשק LayoutShiftAttribution (הסבר מפורט בהמשך). |
value |
הנכס value מדווח על הציון של שינוי בפריסה של שינוי פריסה ספציפי. |
hadRecentInput |
המאפיין hadRecentInput מציין אם התרחש שינוי בפריסה בתוך 500 אלפיות השנייה לאחר קלט של משתמשים. |
startTime |
המאפיין startTime מציין מתי התרחש שינוי בפריסה. הערך startTime מצוין באלפיות השנייה והנמדד ביחס לזמן שבו התחילה טעינת הדף. |
duration |
המאפיין duration תמיד יוגדר כ-0 . הנכס הזה עובר בירושה מהממשק PerformanceEntry (הממשק LayoutShift מרחיב את הממשק PerformanceEntry ). עם זאת, הקונספט של משך זמן לא חל על אירועים של שינוי פריסה, ולכן הוא מוגדר לערך 0 . מידע נוסף על הממשק של PerformanceEntry זמין בspec. |
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, המשמעות היא שהאלמנט הועבר אל מחוץ לאזור התצוגה.
אחד מהדברים הכי חשובים שצריך להבין כשמפרשים את הפלטים האלה הוא שרכיבים שמופיעים בתור מקורות הם הרכיבים שהשתנו במהלך שינוי הפריסה. עם זאת, ייתכן שהאלמנטים האלה קשורים רק באופן עקיף ל'שורש הבעיה' של אי היציבות בפריסה. הנה כמה דוגמאות.
דוגמה ראשונה
שינוי הפריסה הזה ידווח עם מקור אחד: אלמנט B. עם זאת, הגורם הבסיסי לשינוי הפריסה הוא השינוי בגודל של אלמנט A.
דוגמה #2
שינוי הפריסה בדוגמה הזו ידווח באמצעות שני מקורות: אלמנט A ורכיב ב'. הגורם הבסיסי לשינוי הפריסה הוא השינוי במיקום של אלמנט א'.
דוגמה 3
שינוי הפריסה בדוגמה הזו ידווח עם מקור אחד: אלמנט B. שינוי המיקום של רכיב B גרם לשינוי הפריסה הזה.
דוגמה #4
למרות שרכיב B משנה את הגודל, אין שינוי פריסה בדוגמה הזו.
בקישור הבא אפשר לראות הדגמה של האופן שבו שינויים ב-DOM מדווחים על ידי Layout Instability API.
DevTools
חלונית ביצועים
בחלונית Experience של חלונית Performance (ביצועים) בכלי הפיתוח מוצגים כל השינויים בפריסה שמתרחשים במהלך מעקב ביצועים נתון – גם אם הם מתרחשים תוך 500 אלפיות השנייה של אינטראקציה עם המשתמש, ולכן הם לא נכללים ב-CLS. העברת העכבר מעל לשינוי פריסה מסוים בחלונית Experience מדגישה את רכיב ה-DOM המושפע.
כדי לראות מידע נוסף על השינוי בפריסה, לוחצים על שינוי הפריסה ופותחים את חלונית ההזזה Summary. שינויים במאפייני הרכיב מופיעים בפורמט [width, height]
. שינויים במיקום של הרכיב מופיעים בפורמט [x,y]
. המאפיין הקלט האחרון מציין אם התרחש שינוי בפריסה תוך 500 אלפיות השנייה מהאינטראקציה של המשתמש.
כדי לקבל מידע על משך הזמן של שינוי בפריסה, פותחים את הכרטיסייה יומן אירועים. אפשר גם להעריך את משך הזמן של שינוי פריסה על ידי בדיקת האורך של המלבן האדום של שינוי הפריסה בחלונית Experience.
מידע נוסף על השימוש בחלונית ביצועים זמין בחומר העזר בנושא ניתוח ביצועים.
הדגשת האזורים שזזים בפריסה
הדגשת אזורים לשינוי פריסה יכולה להיות שיטה שימושית לקבלת תחושה מהירה ומיידית לגבי המיקום והתזמון של תנודות הפריסה שמתרחשות בדף.
כדי להפעיל את האזורים להזזת הפריסה בכלי הפיתוח, עוברים אל הגדרות > כלים נוספים > רינדור > אזורים של הזזת הפריסה, ואז מרעננים את הדף שרוצים לנפות בו באגים. האזורים של שינוי הפריסה יודגשו לזמן קצר בסגול.
תהליך מחשבה לזיהוי הגורם לשינויים בפריסה
לא משנה מתי או איך מתרחש שינוי הפריסה, תוכלו להשתמש בשלבים הבאים כדי לזהות את הגורם לשינויים בפריסה. אפשר להשלים את השלבים האלה כדי להפעיל את Lighthouse, אבל חשוב לזכור שמערכת Lighthouse יכולה לזהות רק שינויים בפריסה שהתרחשו במהלך הטעינה הראשונית של הדף. בנוסף, Lighthouse יכול לספק הצעות רק מסיבות מסוימות של שינויים בפריסה – לדוגמה, רכיבי תמונה ללא רוחב וגובה מפורשים.
זיהוי הגורם לשינוי פריסה
אלה האירועים שיכולים לגרום לתנודות בפריסה:
- שינויים במיקום של רכיב DOM
- שינויים במאפיינים של רכיב DOM
- הוספה או הסרה של רכיב DOM
- אנימציות שמפעילות פריסה
באופן ספציפי, רכיב ה-DOM שמיד לפני הרכיב שהועבר הוא הרכיב עם הסיכוי הגבוה ביותר להיות מעורב ב'גורם לשינוי' בפריסה. לכן, כשבודקים מה הסיבה לשינוי בפריסה, כדאי:
- האם המיקום או המידות של הרכיב הקודם השתנו?
- האם רכיב DOM נוסף או הוסר לפני הרכיב שהועבר?
- האם המיקום של הרכיב שהועבר השתנה באופן מפורש?
אם הרכיב הקודם לא גרם לשינוי הפריסה, אפשר להמשיך בחיפוש על ידי בדיקת הרכיבים האחרים הקודמים והקרובים.
בנוסף, הכיוון והמרחק של שינוי בפריסה יכולים לספק רמזים לגבי שורש הבעיה. לדוגמה, תזוזה גדולה למטה מציינת לעיתים קרובות את ההוספה של רכיב DOM, בעוד ששינוי פריסה של 1 או 2 פיקסלים בדרך כלל מציין יישום של סגנונות CSS מתנגשים או טעינה ויישום של גופן אינטרנט.
אלה כמה מההתנהגויות הספציפיות שגורמות בתדירות הגבוהה ביותר לאירועים של שינוי פריסה:
שינויים במיקום של אלמנט (שאינם כתוצאה מהתנועה של אלמנט אחר)
סוג השינוי הזה נובע בדרך כלל מהדברים הבאים:
- גיליונות סגנונות שנטענים מאוחר או מחליפים סגנונות שהוצהרו בעבר.
- אפקטים של אנימציה ומעברים.
שינויים במידות של רכיב
סוג השינוי הזה נובע בדרך כלל מהדברים הבאים:
- גיליונות סגנונות שנטענים מאוחר או מחליפים סגנונות שהוצהרו בעבר.
- תמונות ומסגרות iframe ללא המאפיינים
width
ו-height
שנטענים אחרי עיבוד ה "משבצת" שלהם. - בלוקי טקסט ללא המאפיינים
width
אוheight
שמחלפים גופנים אחרי עיבוד הטקסט.
הוספה או הסרה של רכיבי DOM
בדרך כלל הסיבה לכך היא:
- הטמעת מודעות והטמעות אחרות של צד שלישי.
- הוספה של מודעות באנר, התראות וחלונות עזר.
- גלילה מתמשכת ודפוסי חוויית משתמש אחרים שטוענים תוכן נוסף מעל התוכן הקיים.
אנימציות שמפעילות פריסה
חלק מהאפקטים של האנימציה יכולים להפעיל את הפריסה. דוגמה נפוצה לכך היא כשרכיבי 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 בשילוב עם הכלי המועדף לרישום ביומן בממשק הקצה, כדי לאסוף מידע נוסף על הבעיות האלה. בקוד לדוגמה מוסבר איך לעקוב אחרי הרכיב עם התנועה הגדולה ביותר בדף.