Largest Contentful Paint (LCP)

תמיכה בדפדפן

  • Chrome: 77.
  • קצה: 79.
  • Firefox: 122.
  • Safari: לא נתמך.

מקור

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

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

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

מה זה LCP?

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

מהו ציון LCP טוב?

כדי לספק חוויית משתמש טובה, מומלץ שגודל התוכן באתר יהיה הכי גדול (LCP) באורך של 2.5 שניות לכל היותר. כדי לוודא שאתם עומדים ביעד הזה עבור רוב המשתמשים, סף טוב למדידה הוא האחוזון ה-75 של טעינות דפים, המפולחים במכשירים ניידים ובמחשבים.

ערכי LCP טובים הם 2.5 שניות לכל היותר, ערכים נמוכים הם גדולים מ-4.0 שניות וכל מה שביניהם צריך לשפר
ערך LCP טוב הוא 2.5 שניות לכל היותר.

אילו אלמנטים נחשבים?

כפי שמצוין כרגע ב-LCP API, סוגי הרכיבים נחשבים ל- Largest Contentful Paint (LCP) הם:

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

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

דוגמאות

הנה כמה דוגמאות למצבים שבהם מוצג ה- Largest Contentful Paint (LCP) בכמה אתרים פופולריים:

ציר הזמן Largest Contentful Paint (LCP) מ-cnn.com
ציר זמן של LCP מ-cnn.com.
ציר הזמן Largest Contentful Paint (LCP) מאתר techcrunch.com
ציר זמן LCP מ-techcrunch.com.

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

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

ציר הזמן Largest Contentful Paint (LCP) מ-instagram.com
ציר זמן LCP מ-instagram.com.
ציר הזמן Largest Contentful Paint (LCP) מ-google.com
ציר זמן LCP מ-google.com.

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

איך מודדים LCP

אפשר למדוד LCP בשיעור ה-Lab או בשדה, והוא זמין בכלים הבאים:

כלים לשטח

כלים לשיעור 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.