אופטימיזציה של Largest Contentful Paint (LCP)

מדריך מפורט בנושא פירוט של LCP וזיהוי תחומים מרכזיים לשיפור.

תאריך פרסום: 30 באפריל 2020

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

כדי לספק חוויית משתמש טובה, האתרים צריכים לשאוף להגיע ל-LCP של 2.5 שניות או פחות ב-75% לפחות מהביקורים בדפים.

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

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

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

הסבר על המדד LCP

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

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

אפשר להציג נתוני LCP שמבוססים על משתמשים אמיתיים באמצעות כלים למעקב אחר משתמשים אמיתיים (RUM) שמותקנים באתר, או באמצעות הדוח על חוויית המשתמש ב-Chrome‏ (CrUX), שבו נאספים נתונים אנונימיים ממשתמשי Chrome אמיתיים עבור מיליוני אתרים.

שימוש בנתוני LCP של CrUX בכלי הפיתוח ל-Chrome

בחלונית 'ביצועים' בכלי הפיתוח ל-Chrome מוצגת חוויית ה-LCP המקומית לצד מדד ה-LCP של הדף או המקור ב-CrUX, בתצוגת המדדים הפעילים.

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

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

שימוש בנתוני LCP של CrUX ב-PageSpeed Insights

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

נתוני CrUX שמוצגים ב-PageSpeed Insights
נתוני CrUX שמוצגים ב-PageSpeed Insights.

ב-PageSpeed Insights מוצגים עד ארבעה נתוני CrUX שונים:

  • נתונים לנייד לגבי כתובת ה-URL הזו
  • נתונים ממחשב לגבי כתובת ה-URL הזו
  • נתוני נייד לכל המקור
  • נתוני מחשב לכל המקור

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

מערכת PageSpeed Insights עוברת לנתונים ברמת המקור כשאין נתונים ברמת כתובת ה-URL
כשאין ב-PageSpeed Insights נתונים ברמת כתובת ה-URL, מוצגים נתונים ברמת המקור.

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

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

שימוש במדדים המשניים של CrUX ב-PageSpeed Insights

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

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

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

אחרי שהדף מתחיל עיבוד, יכול להיות שיופיע ציור ראשוני (למשל צבע הרקע), ולאחר מכן יופיע תוכן כלשהו (למשל כותרת האתר). המדד 'הצגת תוכן ראשוני (FCP)' מודד את ההופעה של התוכן הראשוני. ההפרש בין מדד FCP לבין מדדים אחרים יכול להיות משמעותי מאוד.

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

אם יש פער גדול בין FCP ל-LCP, סימן שמקור ה-LCP לא זמין באופן מיידי לדפדפן כדי לתת לו עדיפות (לדוגמה, טקסט או תמונות שמנוהלים על ידי JavaScript ולא זמינים ב-HTML הראשוני), או שהדפדפן משלים משימות אחרות לפני שהוא יכול להציג את תוכן ה-LCP.

שימוש בנתוני Lighthouse של PageSpeed Insights

בקטע Lighthouse בכלי PageSpeed Insights מפורטות כמה הנחיות לשיפור ה-LCP, אבל קודם כדאי לבדוק אם ה-LCP שצוין תואם באופן כללי לנתוני משתמשים אמיתיים שסופקו על ידי CrUX. אם יש אי-התאמה בין Lighthouse לבין CrUX, סביר להניח ש-CrUX מספק תמונה מדויקת יותר של חוויית המשתמש. לפני שמבצעים פעולות על סמך נתוני CrUX, חשוב לוודא שהם מתייחסים לדף ולא למקור המלא.

אם גם ב-Lighthouse וגם ב-CrUX מוצגים ערכים של LCP שדורשים שיפור, בקטע Lighthouse תוכלו למצוא הנחיות חשובות לגבי דרכים לשיפור ה-LCP. אפשר להשתמש במסנן LCP כדי להציג רק ביקורות שרלוונטיות ל-LCP באופן הבא:

הזדמנויות ואבחון של LCP ב-Lighthouse
אבחונים והצעות של Lighthouse לשיפור LCP.

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

שלבי LCP ב-Lighthouse
פירוט של רכיבי LCP ב-Lighthouse.

בהמשך נתעמק בחלקים המשניים האלה.

פירוט של LCP

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

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

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

  1. מסמך ה-HTML הראשוני
  2. משאב ה-LCP (אם רלוונטי)

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

כדי לזהות את המשאב של LCP, אפשר להשתמש בכלים למפתחים (כמו PageSpeed Insights שצוין קודם, כלי הפיתוח ל-Chrome או WebPageTest) כדי לקבוע את רכיב ה-LCP. משם אפשר להתאים את כתובת ה-URL (שוב, אם רלוונטי) שנטענת על ידי האלמנט במפל הרשת של כל המשאבים שנטענים על ידי הדף.

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

רשימת רשתות ב-Waterfall עם הדגשה של משאבי ה-HTML ו-LCP
תרשים מפל שבו מוצגים זמני הטעינה של ה-HTML בדף אינטרנט והמשאבים הנדרשים ל-LCP.

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

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

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

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

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

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

לדוגמה, בתרשים רשימת הרשתות הקודם, אם תקטינו את גודל הקובץ של התמונה על ידי דחיסתה יותר או מעבר לפורמט אופטימלי יותר (כמו AVIF או WebP), משך טעינת המשאב יהיה קצר יותר, אבל זמן ה-LCP לא ישתפר כי הזמן פשוט יועבר לחלק המשני עיכוב עיבוד הרכיב:

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

הסיבה לכך היא שבדף הזה, רכיב ה-LCP מוסתר עד שהטעינה של קוד ה-JavaScript מסתיימת, ואז הכל נחשף בבת אחת.

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

זמני חלקים משניים אופטימליים

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

מתוך ארבעת החלקים המשניים, בשני השמות מופיעה המילה 'delay' (עיכוב). זהו רמז לכך שרצוי שהזמנים האלה יהיו קרובים לאפס ככל האפשר. שני החלקים האחרים כוללים בקשות לרשת, שתהליך הטיפול בהן אורך זמן.

חלק משנה של LCP אחוז LCP
המהירות שבה מגיע בייט התגובה הראשון (TTFB) ‎~40%
עיכוב בטעינת המשאבים <10%
משך הטעינה של משאבים ‎~40%
עיכוב בעיבוד הרכיב <10%
TOTAL 100%

חשוב לזכור שהחלוקות האלה לזמנים הן הנחיות, ולא כללים קפדניים. אם זמני ה-LCP בדפים שלכם נעים בטווח של 2.5 שניות באופן עקבי, לא משנה מהם היחסים היחסיים. עם זאת, אם אתם מבזבזים הרבה זמן מיותר באחד מהחלקים של 'השהיה', יהיה מאוד קשה לעמוד באופן קבוע ביעד של 2.5 שניות.

דרך טובה לחשוב על פירוט זמן ה-LCP היא:

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

איך מבצעים אופטימיזציה של כל חלק

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

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

1. ביטול העיכוב בטעינת המשאבים

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

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

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

באופן כללי, יש שני גורמים שמשפיעים על המהירות שבה משאב LCP יכול להיטען:

  • כשהמשאב מתגלה.
  • העדיפות של המשאב.

אופטימיזציה כשהמשאב מתגלה

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

  • אלמנט ה-LCP הוא אלמנט <img>, והמאפיינים src או srcset שלו נמצאים בסימון ה-HTML הראשוני.
  • רכיב ה-LCP מחייב תמונת רקע ב-CSS, אבל התמונה הזו נטענת מראש באמצעות <link rel="preload"> בתגי העיצוב של ה-HTML (או באמצעות כותרת Link).
  • רכיב ה-LCP הוא צומת טקסט שדורש גופן אינטרנט לעיבוד (רנדור). הגופן נטען באמצעות <link rel="preload"> בסימון ה-HTML (או באמצעות כותרת Link).

ריכזנו כאן כמה דוגמאות למקרים שבהם לא ניתן לזהות את משאב ה-LCP על ידי סריקת התגובה של מסמך ה-HTML:

  • רכיב ה-LCP הוא <img> שנוסף באופן דינמי לדף באמצעות JavaScript.
  • אלמנט ה-LCP נטען באיטרציה באמצעות ספריית JavaScript שמסתירה את המאפיינים src או srcset שלו (לרוב כ-data-src או data-srcset).
  • רכיב ה-LCP מחייב תמונת רקע ב-CSS.

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

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

<!-- Load the stylesheet that will reference the LCP image. -->
<link rel="stylesheet" href="/path/to/styles.css">

<!-- Preload the LCP image with a high fetchpriority so it starts loading with the stylesheet. -->
<link rel="preload" fetchpriority="high" as="image" href="/path/to/hero-image.webp" type="image/webp">

אופטימיזציה של העדיפות של המשאב

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

לדוגמה, אפשר לעכב את הצגת התמונה של ה-LCP באמצעות HTML אם מגדירים את הערך loading="lazy" ברכיב <img>. כשמשתמשים בטעינה איטית, המשאב לא נטען עד שהפריסה מאשרת שהתמונה נמצאת בחלון התצוגה, ולכן הטעינה עשויה להתחיל מאוחר יותר מאשר במקרה אחר.

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

<img fetchpriority="high" src="/path/to/hero-image.webp">

מומלץ להגדיר את fetchpriority="high" ברכיב <img> אם לדעתכם סביר שהוא רכיב ה-LCP של הדף. עם זאת, הגדרת עדיפות גבוהה ליותר מתמונה אחת או שתיים לא תעזור בהפחתת זמן הטעינה של התוכן הוויזואלי.

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

<img fetchpriority="low" src="/path/to/carousel-slide-3.webp">

אם תבטלו את העדיפות של משאבים מסוימים, תוכלו להקצות יותר רוחב פס למשאבים שזקוקים לו יותר – אבל חשוב להיזהר. תמיד צריך לבדוק את העדיפות של המשאבים ב-DevTools ולבדוק את השינויים באמצעות הכלים של Lab ושל שדה.

אחרי שתבצעו אופטימיזציה של תזמון הגילוי והעדיפות של משאב ה-LCP, רשימת הרשתות ב-Waterfall אמורה להיראות כך (משאב ה-LCP מתחיל באותו זמן כמו המשאב הראשון):

תרשים Waterfall של רשת שבו מוצג משאב ה-LCP שמתחיל עכשיו באותו זמן כמו המשאב הראשון
משאב ה-LCP מתחיל להיטען עכשיו באותו זמן שבו נטענת גיליון הסגנונות.

2. ביטול העיכוב בעיבוד הרכיב

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

הסיבה העיקרית לכך שרכיב ה-LCP לא יוכל להיראות מיד אחרי שהמשאב שלו יסיים להיטען היא אם העיבוד חסום מסיבה אחרת:

  • הטעינה של כל הדף נחסמת בגלל גיליונות סגנונות או סקריפטים סינכרוניים ב-<head> שעדיין נטענים.
  • משאב ה-LCP סיים את הטעינה, אבל רכיב ה-LCP עדיין לא נוסף ל-DOM (הוא מחכה לטעינה של קוד JavaScript מסוים).
  • הרכיב מוסתר על ידי קוד אחר, כמו ספריית בדיקות A/B שעדיין קובעת באיזה ניסוי המשתמש צריך להשתתף.
  • ה-thread הראשי חסום בגלל משימות ארוכות, ועבודת העיבוד צריכה להמתין עד שהמשימות הארוכות האלה יסתיימו.

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

צמצום או הטמעה בקוד של גיליונות סגנונות שחוסמים את העיבוד

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

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

כדי לפתור את הבעיה, אפשר:

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

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

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

ריכזנו כאן כמה המלצות להקטנת הגודל של גיליון הסגנונות:

  • הסרת CSS שלא בשימוש: משתמשים בכלים למפתחים של Chrome כדי למצוא כללי CSS שלא בשימוש ואפשר להסיר אותם (או לדחות אותם).
  • דחיית CSS לא קריטי: כדאי לפצל את גיליון הסגנונות לסגנונות שנדרשים לטעינת הדף הראשונית, ולאחר מכן לסגנונות שאפשר לטעון בצורה עצלה.
  • צמצום וקידוד של CSS: לגבי סגנונות חיוניים, חשוב להקטין את גודל ההעברה שלהם ככל האפשר.

דחייה או הטמעה בקוד של קוד JavaScript שחוסם את העיבוד

כמעט אף פעם אין צורך להוסיף סקריפטים סינכרוניים (סקריפטים ללא המאפיינים async או defer) ל-<head> של הדפים, וכמעט תמיד הפעולה הזו תשפיע לרעה על הביצועים.

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

מה אסור לעשות
<head>
 
<script src="/path/to/main.js"></script>
</head>
מה מותר לעשות
<head>
 
<script>
   
// Inline script contents directly in the HTML.
   
// IMPORTANT: only do this for very small scripts.
 
</script>
</head>

שימוש ברינדור בצד השרת

עיבוד בצד השרת (SSR) הוא תהליך שבו מריצים את הלוגיקה של האפליקציה בצד הלקוח בשרת, ומגיבים לבקשות של מסמכי HTML באמצעות ה-HTML markup המלא.

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

  • משאבי התמונות יהיו גלויים ממקור ה-HTML (כפי שמתואר בשלב 1 למעלה).
  • תוכן הדף לא ידרוש בקשות JavaScript נוספות כדי להסתיים לפני שהוא יוכל להירטן.

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

אפשרות דומה ל-SSR נקראת יצירת אתר סטטי (SSG) או עיבוד מראש. זהו התהליך שבו דפי ה-HTML נוצרים בשלב ה-build ולא על פי דרישה. אם אפשר לבצע עיבוד מראש בארכיטקטורה שלכם, בדרך כלל זו הבחירה הטובה ביותר מבחינת הביצועים.

פיצול משימות ארוכות

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

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

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

3. קיצור משך הטעינה של המשאבים

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

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

הקטנת הגודל של המשאב

משאב ה-LCP של דף (אם יש לו כזה) יהיה תמונה או גופן אינטרנט. במדריכים הבאים מוסבר בפירוט איך לצמצם את הגודל של שניהם:

צמצום המרחק שהמשאב צריך לעבור

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

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

צמצום התחרות על רוחב הפס של הרשת

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

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

להסיר לחלוטין את זמן הרשת

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

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

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

4. צמצום הזמן לקבלת בייט התגובה הראשון (TTFB)

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

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

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

הנחיות ספציפיות לאופטימיזציה של זמן אחזור ה-TTFB מפורטות במדריך לאופטימיזציה של זמן אחזור ה-TTFB.

מעקב אחר פירוט של LCP ב-JavaScript

נתוני התזמון של כל החלקים המשניים של LCP שצוינו למעלה זמינים ב-JavaScript באמצעות שילוב של ממשקי ה-API הבאים למדידת ביצועים:

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

לדוגמה, בצילום המסך הבא נעשה שימוש בשיטה performance.measure() מ-User Timing API כדי להוסיף עמודות לטראק 'זמנים' בחלונית הביצועים של כלי הפיתוח ל-Chrome.

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

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

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

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

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

שתי התצוגות החזותיות האלה נוצרו באמצעות הקוד הבא:

const LCP_SUB_PARTS = [
 
'Time to first byte',
 
'Resource load delay',
 
'Resource load duration',
 
'Element render delay',
];

new PerformanceObserver((list) => {
 
const lcpEntry = list.getEntries().at(-1);
 
const navEntry = performance.getEntriesByType('navigation')[0];
 
const lcpResEntry = performance
   
.getEntriesByType('resource')
   
.filter((e) => e.name === lcpEntry.url)[0];

 
// Ignore LCP entries that aren't images to reduce DevTools noise.
 
// Comment this line out if you want to include text entries.
 
if (!lcpEntry.url) return;

 
// Compute the start and end times of each LCP sub-part.
 
// WARNING! If your LCP resource is loaded cross-origin, make sure to add
 
// the `Timing-Allow-Origin` (TAO) header to get the most accurate results.
 
const ttfb = navEntry.responseStart;
 
const lcpRequestStart = Math.max(
    ttfb
,
   
// Prefer `requestStart` (if TOA is set), otherwise use `startTime`.
    lcpResEntry
? lcpResEntry.requestStart || lcpResEntry.startTime : 0
 
);
 
const lcpResponseEnd = Math.max(
    lcpRequestStart
,
    lcpResEntry
? lcpResEntry.responseEnd : 0
 
);
 
const lcpRenderTime = Math.max(
    lcpResponseEnd
,
   
// Use LCP startTime (the final LCP time) because there are sometimes
   
// slight differences between loadTime/renderTime and startTime
   
// due to rounding precision.
    lcpEntry
? lcpEntry.startTime : 0
 
);

 
// Clear previous measures before making new ones.
 
// Note: due to a bug, this doesn't work in Chrome DevTools.
  LCP_SUB_PARTS
.forEach((part) => performance.clearMeasures(part));

 
// Create measures for each LCP sub-part for easier
 
// visualization in the Chrome DevTools Performance panel.
 
const lcpSubPartMeasures = [
    performance
.measure(LCP_SUB_PARTS[0], {
      start
: 0,
      end
: ttfb,
   
}),
    performance
.measure(LCP_SUB_PARTS[1], {
      start
: ttfb,
      end
: lcpRequestStart,
   
}),
    performance
.measure(LCP_SUB_PARTS[2], {
      start
: lcpRequestStart,
      end
: lcpResponseEnd,
   
}),
    performance
.measure(LCP_SUB_PARTS[3], {
      start
: lcpResponseEnd,
      end
: lcpRenderTime,
   
}),
 
];

 
// Log helpful debug information to the console.
  console
.log('LCP value: ', lcpRenderTime);
  console
.log('LCP element: ', lcpEntry.element, lcpEntry.url);
  console
.table(
    lcpSubPartMeasures
.map((measure) => ({
     
'LCP sub-part': measure.name,
     
'Time (ms)': measure.duration,
     
'% of LCP': `${
       
Math.round((1000 * measure.duration) / lcpRenderTime) / 10
     
}%`,
   
}))
 
);
}).observe({type: 'largest-contentful-paint', buffered: true});

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

סיכום

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

באופן כללי, אפשר לסכם את האופטימיזציה של LCP בארבעה שלבים:

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

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