בעבר, מפתחי אתרים התקשו למדוד את מהירות הטעינה של התוכן הראשי בדף אינטרנט והוא גלוי למשתמשים. מדדים ישנים יותר כמו load או DOMContentLoaded לא פועלים כראוי, כי הם לא בהכרח תואמים למה שהמשתמש רואה במסך. בנוסף, מדדי ביצועים חדשים יותר שמתמקדים במשתמש, כמו הצגת תוכן ראשוני (FCP), מתעדים רק את ההתחלה של חוויית הטעינה. אם מוצג בדף מסך פתיחה או אינדיקטור לטעינה, הרגע הזה לא רלוונטי במיוחד למשתמש.
בעבר המלצנו על מדדי ביצועים כמו המהירות שבה נטען רכיב חשוב קודם (FMP) ואינדקס המהירות (SI) (שניהם זמינים ב-Lighthouse) כדי לתעד יותר את חוויית הטעינה אחרי הבדיקה הראשונית. אבל המדדים האלה מורכבים, קשים להסבר ולרוב שגויים – ולכן עדיין אי אפשר לזהות מתי התוכן העיקרי של הדף נטען.
בהתבסס על דיונים בקבוצת העבודה של W3C באינטרנט בנושא ביצועים באינטרנט ומחקרים שביצענו ב-Google, גילינו שכדי למדוד מתי התוכן העיקרי של דף נטען, בודקים מתי מתבצע עיבוד הרכיב הגדול ביותר.
מה זה LCP?
התכונה LCP מדווחת על זמן העיבוד של בלוק התמונה או הטקסט הגדול ביותר שמוצג באזור התצוגה, ביחס לזמן שבו המשתמש ניווט לראשונה לדף.
מהו ציון LCP טוב?
כדי לספק חוויית משתמש טובה, מומלץ שגודל התוכן באתר יהיה הכי גדול (LCP) באורך של 2.5 שניות לכל היותר. כדי לוודא שאתם עומדים ביעד הזה עבור רוב המשתמשים, סף טוב למדידה הוא האחוזון ה-75 של טעינות דפים, המפולחים במכשירים ניידים ובמחשבים.
אילו אלמנטים נחשבים?
כפי שמצוין כרגע ב-LCP API, סוגי הרכיבים נחשבים ל- Largest Contentful Paint (LCP) הם:
- רכיבי
<img>
(זמן ההצגה בפריים הראשון משמש לתוכן מונפש, כמו קובצי GIF או קובצי PNG מונפשים) - רכיבי
<image>
בתוך רכיב<svg>
- רכיבי
<video>
(זמן הטעינה של תמונת הפוסטר או זמן ההצגה של הפריים הראשון עבור סרטונים – המוקדם מביניהם) - רכיב עם תמונת רקע שנטען באמצעות הפונקציה
url()
(בניגוד להדרגתיות של CSS) - רכיבים ברמת הבלוק שמכילים צומתי טקסט או רכיבי טקסט אחרים ברמה מוטבעת.
שימו לב שהגבלת הרכיבים לקבוצה המוגבלת הזו הייתה מכוונת, כדי שהעניין יהיה פשוט מלכתחילה. בעתיד ייתכן שנוסיף עוד רכיבים (כמו התמיכה המלאה ב-<svg>
) ככל שייערך מחקר נוסף.
בנוסף להתחשבות רק באלמנטים מסוימים, מדידות LCP משתמשות בהיוריסטיקה כדי להחריג רכיבים מסוימים שסביר להניח שהמשתמשים יראו כ"לא מכילים תוכן". דוגמאות לדפדפנים המבוססים על Chromium:
- רכיבים עם שקיפות 0, שאינם גלויים למשתמש
- רכיבים שמכסים את אזור התצוגה המלא, שסביר להניח שנחשבים כרקע ולא כתוכן
- תמונות placeholder או תמונות אחרות עם אנטרופיה נמוכה, שסביר להניח שלא משקפות את התוכן האמיתי של הדף
סביר להניח שדפדפנים ימשיכו לשפר את היוריסטיקה הזו כדי להבטיח שאנחנו מתאימים לציפיות של המשתמשים לגבי רכיב התוכן הגדול ביותר.
הערכים ה"תוכןיים" האלה היוריסטיקה שונה מההיוריסטיקה שמשמשת את המהירות שבה נטען רכיב התוכן הראשון (FCP), ולכן המערכת עשויה להביא בחשבון חלק מהאלמנטים האלה, כמו תמונות placeholder או תמונות של אזור התצוגה המלא, גם אם הם לא עומדים בדרישות של ה-LCP. למרות ששניהם משתמשים בתוכן "תוכן" השם שלהם שונה, המטרה של המדדים האלה היא שונה. שיטת FCP מודדת מקרים שבהם תוכן כלשהו צבוע למסך ו-LCP כשהתוכן הראשי צבוע, כך שכלי ה-LCP אמור להיות סלקטיבי יותר.
איך נקבע גודל הרכיב?
גודל הרכיב שדווח לגבי LCP הוא בדרך כלל הגודל שגלוי למשתמש באזור התצוגה. אם הרכיב מתפרס מחוץ לאזור התצוגה, או אם רכיב אחד מהרכיבים שלו נחתך או כולל אפשרויות נוספות לא גלויות, החלקים האלה לא יחושבו כחלק מגודל הרכיב.
ברכיבי תמונה שגודלם השתנה מהגודל הפנימי שלהם, הגודל המדווח הוא הגודל הגלוי או הגודל הפנימי, הקטן מביניהם.
ברכיבי טקסט, הפונקציה LCP מתייחסת רק למלבן הקטן ביותר שיכול להכיל את כל צומתי הטקסט.
בכל האלמנטים, שיטת LCP לא מביאה בחשבון שוליים, מרווחים פנימיים או גבולות שהוחלו באמצעות CSS.
מתי מדווח LCP?
דפי אינטרנט נטענים בדרך כלל בשלבים, ולכן ייתכן שהרכיב הגדול ביותר בדף ישתנה.
כדי להתמודד עם פוטנציאל השינוי הזה, הדפדפן שולח PerformanceEntry
מסוג largest-contentful-paint
שמזהה את הרכיב הגדול ביותר עם תוכן ברגע שהדפדפן צייר את הפריים הראשון. אבל, אחרי עיבוד הפריימים הבאים, האפליקציה תשלח עוד PerformanceEntry
בכל פעם שיבוצע שינוי ברכיב התוכן הגדול ביותר.
לדוגמה, בדף עם טקסט ותמונה ראשית, הדפדפן עשוי בהתחלה רק לעבד את הטקסט - לאחר מכן הדפדפן ישלח רשומת largest-contentful-paint
שבה המאפיין element
יתייחס כנראה ל-<p>
או ל-<h1>
. מאוחר יותר, ברגע שטעינת התמונה הראשית (Hero) תסתיים, תישלח רשומה שנייה של largest-contentful-paint
, והמאפיין element
שלה יפנה אל <img>
.
רכיב יכול להיחשב כרכיב התוכן הגדול ביותר רק אחרי שהוא עבר רינדור וגלוי למשתמש. תמונות שעדיין לא נטענו לא נחשבות כ'רינדור'. גם לא צמתי טקסט שמשתמשים בגופני אינטרנט במהלך התקופה של חסימת הגופנים. במקרים כאלה, יכול להיות שידווח על רכיב קטן יותר כרכיב התוכן הגדול ביותר, אבל ברגע שהעיבוד של הרכיב הגדול יותר יסתיים, ייווצר PerformanceEntry
נוסף.
בנוסף לתמונות וגופנים שנטענים מאוחרים, דף עשוי להוסיף רכיבים חדשים ל-DOM כאשר תוכן חדש הופך לזמין. אם אחד מהרכיבים החדשים האלה גדול יותר מהרכיב הקודם הגדול ביותר עם תוכן, יופיע גם ערך PerformanceEntry
חדש.
אם רכיב התוכן הגדול ביותר מוסר מאזור התצוגה, או אפילו מה-DOM, הוא נשאר הרכיב הגדול ביותר בעל התוכן, אלא אם מתבצע עיבוד של רכיב גדול יותר.
הדפדפן יפסיק לדווח על רשומות חדשות ברגע שהמשתמש יוצר אינטראקציה עם הדף (באמצעות הקשה, גלילה או הקשה על מקש), כי אינטראקציה של המשתמש משנה לעיתים קרובות את מה שגלוי למשתמש (הדבר נכון במיוחד לגבי גלילה).
למטרות ניתוח, יש לדווח רק על PerformanceEntry
שנשלח לאחרונה לשירות ניתוח הנתונים שלך.
זמן הטעינה לעומת זמן הרינדור
מטעמי אבטחה, חותמת הזמן של העיבוד של תמונות לא נחשפת לתמונות ממקורות שונים ללא הכותרת Timing-Allow-Origin
. במקום זאת, רק זמן הטעינה שלהם נחשף (מכיוון שזמן הטעינה הזה כבר נחשף דרך ממשקי API רבים אחרים לאינטרנט).
זה עלול להוביל למצב שנראה בלתי אפשרי שבו LCP מדווח על ידי ממשקי API באינטרנט מוקדם יותר מ-FCP. זה לא המצב, אלא נראה כך רק בגלל הגבלת האבטחה הזו.
כשהדבר אפשרי, מומלץ תמיד להגדיר את הכותרת Timing-Allow-Origin
כדי שהמדדים יהיו מדויקים יותר.
איך מטפלים בשינויים מבחינת הפריסה והגודל של רכיבים?
כדי שתקורת הביצועים של החישוב והשליחה של רשומות ביצועים חדשות תהיה נמוכה, שינויים בגודל או במיקום של הרכיב לא יוצרים מועמדים חדשים ל-LCP. המערכת מביאה בחשבון רק את הגודל והמיקום הראשוני של הרכיב באזור התצוגה.
המשמעות היא שיכול להיות שלא יהיה ניתן לדווח על תמונות שמעובדות בהתחלה מחוץ למסך ולאחר מכן מועברות למסך. זה גם אומר שרכיבים שעברו רינדור ראשוני באזור התצוגה ולאחר מכן נדחפים למטה, מחוץ לתצוגה עדיין ידווחו בגודל הראשוני של אזור התצוגה.
דוגמאות
הנה כמה דוגמאות למקרים שבהם ה-LCP מתרחש בכמה אתרים פופולריים:
בשני צירי הזמן שלמעלה, הרכיב הגדול ביותר משתנה ככל שהתוכן נטען. בדוגמה הראשונה, המערכת מוסיפה תוכן חדש ל-DOM ומשנה את הרכיב הגדול ביותר. בדוגמה השנייה, הפריסה משתנה והתוכן שהיה בעבר הגדול ביותר מוסר מאזור התצוגה.
במקרים רבים תוכן שנטען מאוחר הוא גדול יותר מתוכן שכבר נמצא בדף, אך אין זה בהכרח נכון. שתי הדוגמאות הבאות מראות את ה-LCP שמתרחש לפני שהדף נטען במלואו.
בדוגמה הראשונה, הלוגו של Instagram נטען מוקדם יחסית, והוא נשאר המרכיב הגדול ביותר גם כאשר תוכן אחר מוצג בהדרגה. בדוגמה של דף תוצאות החיפוש ב-Google, האלמנט הגדול ביותר הוא פסקת טקסט שמוצגת לפני שטעינת התמונות או הלוגו מסתיימת. מאחר שכל התמונות הנפרדות קטנות יותר מפסקה זו, היא נשארה המרכיב הגדול ביותר בתהליך הטעינה.
איך מודדים LCP
אפשר למדוד LCP בשיעור ה-Lab או בשדה, והוא זמין בכלים הבאים:
כלים לשטח
- הדוח על חוויית המשתמש ב-Chrome
- PageSpeed Insights
- Search Console (דוח מדדי הליבה לבדיקת חוויית המשתמש באתר)
- ספריית JavaScript של
web-vitals
כלים לשיעור Lab
מדידת LCP ב-JavaScript
כדי למדוד LCP ב-JavaScript, אפשר להשתמש ב-Largest Contentful Paint API. הדוגמה הבאה מראה איך ליצור PerformanceObserver
שמקשיב לרשומות של largest-contentful-paint
ומרשום אותן במסוף.
new PerformanceObserver((entryList) => {
for (const entry of entryList.getEntries()) {
console.log('LCP candidate:', entry.startTime, entry);
}
}).observe({type: 'largest-contentful-paint', buffered: true});
בדוגמה שלמעלה, כל רשומת largest-contentful-paint
ביומן מייצגת את אלמנט ה-LCP הנוכחי. באופן כללי, ערך startTime
של הרשומה האחרונה שהתקבלה הוא ערך ה-LCP. עם זאת, זה לא תמיד נכון. לא כל הערכים של largest-contentful-paint
תקינים למדידת LCP.
בקטע הבא מפורטים ההבדלים בין הדוחות של ה-API לבין אופן החישוב של המדד.
ההבדלים בין המדד לבין ה-API
- ה-API ישלח
largest-contentful-paint
רשומות של דפים שנטענים בכרטיסיית רקע, אבל צריך להתעלם מהדפים האלה בחישוב LCP. - ה-API ימשיך לשלוח
largest-contentful-paint
רשומות אחרי שדף הועבר לרקע, אבל צריך להתעלם מרשומות אלה בעת חישוב LCP (ניתן להתייחס לרכיבים רק אם הדף היה בחזית במשך כל הזמן). - ה-API לא מדווח על רשומות
largest-contentful-paint
כשהדף שוחזר ממטמון לדף הקודם/הבא, אבל צריך למדוד LCP במקרים כאלה, כי המשתמשים חווים אותן כביקורים נפרדים בדף. - ה-API לא מתייחס לרכיבים שבתוך מסגרות iframe, אבל המדד כן מתייחס אליהם כפי שהם חלק מחוויית המשתמש בדף. בדפים עם LCP בתוך iframe – לדוגמה תמונת פוסטר בסרטון מוטמע – ההסבר הזה יוצג כהבדל בין CrUX ל-RUM. כדי למדוד LCP כראוי, צריך לשקול אותם. תמונות משנה יכולות להשתמש ב-API כדי לדווח על רשומות
largest-contentful-paint
שלהן למסגרת ההורה לצורך צבירה. - ה-API מודד את מדד ה-LCP מתחילת הניווט, אבל בדפים שעברו עיבוד מראש צריך למדוד את ה-LCP ב-
activationStart
כי זה תואם לזמן ה-LCP כפי שראה המשתמש.
במקום לשנן את כל ההבדלים הקלים האלה, מפתחים יכולים להשתמש בספריית ה-JavaScript של web-vitals
כדי למדוד את ה-LCP, שמטפל בהבדלים האלה בשבילכם (כשהדבר אפשרי – שימו לב שהבעיה 'iframe לא כלולה'):
import {onLCP} from 'web-vitals';
// Measure and log LCP as soon as it's available.
onLCP(console.log);
בקוד המקור של onLCP()
תמצאו דוגמה מלאה למדידת LCP ב-JavaScript.
מה קורה אם האלמנט הגדול ביותר הוא לא החשוב ביותר?
במקרים מסוימים, הרכיב (או הרכיבים) החשובים ביותר בדף אינו זהה לרכיב הגדול ביותר, ובמקום זאת ייתכן שמפתחים ירצו למדוד את זמני העיבוד של רכיבים אחרים אלה. הדבר אפשרי באמצעות Element Timing API, כפי שמתואר במאמר בנושא מדדים מותאמים אישית.
איך לשפר את מדד ה-LCP
ניתן למצוא מדריך מלא בנושא אופטימיזציה של LCP, שינחה אתכם בתהליך הזיהוי של תזמוני LCP בשטח ובשימוש בנתוני שיעור ה-Lab כדי להציג פירוט ולבצע אופטימיזציה של הנתונים.
מקורות מידע נוספים
יומן שינויים
מדי פעם מתגלים באגים בממשקי ה-API שמשמשים למדידת מדדים, ולפעמים גם בהגדרות של המדדים עצמם. כתוצאה מכך, לפעמים צריך לבצע שינויים, והשינויים יכולים להופיע כשיפורים או כרגרסיות בדוחות הפנימיים ובלוחות הבקרה.
כדי לעזור לכם לנהל את זה, כל השינויים בהטמעה או בהגדרה של המדדים האלה יופיעו ביומן השינויים הזה.
אם יש לכם משוב על המדדים האלה, אתם יכולים לשלוח אותו בקבוצת Google בנושא web-vitals-feedback.