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

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

מהם רמזים מוקדמים?

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

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

Early Hints הוא קוד מצב HTTP (103 Early Hints) שמשמש לשליחת תגובה ראשונית של HTTP לפני התגובה הסופית. כך השרת יכול לשלוח לרשת הדפדפן רמזים לגבי משאבי משנה חיוניים (למשל, גיליונות סגנונות של הדף, JavaScript חיוני) או מקורות שבהם הדף צפוי להשתמש, בזמן שהשרת עסוק ביצירת המשאב הראשי. הדפדפן יכול להשתמש בהצעות האלה כדי לחמם את החיבורים ולבקש משאבי משנה, בזמן ההמתנה למשאב הראשי. במילים אחרות, הטיפים המוקדמים עוזרים לדפדפן לנצל את 'זמן החשיבה של השרת' על ידי ביצוע עבודה מסוימת מראש, וכך להאיץ את טעינת הדפים.

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

במקרים מסוימים, שיפור הביצועים של Largest Contentful Paint יכול להגיע לכמה מאות אלפיות השנייה, כפי שציינו ב-Shopify וב-Cloudflare, ועד לשיפור של שנייה אחת, כפי שרואים בהשוואה הזו לפני ואחרי:

השוואה בין שני אתרים.
השוואה בין נתונים לפני ואחרי שימוש ב-Early Hints באתר בדיקה שנערך באמצעות WebPageTest‏ (Moto G4 – DSL)

איך משתמשים ב-Early Hints

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

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

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

כשמשתמשים בהם ב-HTML, בדרך כלל רוצים preconnect או preload משאבים שסורק ההטענה מראש לא יזהה ב-HTML – לדוגמה, גופנים או תמונות רקע, שבמקרה אחר יימצאו מאוחר יותר. כשמשתמשים ב-Early Hints, אין לכם את ה-HTML, לכן מומלץ במקום זאת להשתמש ב-preconnect לדומיינים קריטיים או ב-preload למשאבים קריטיים שיכול להיות שיימצאו מוקדם יותר ב-HTML – לדוגמה, טעינת main.css או app.js מראש.בנוסף, לא כל הדפדפנים תומכים ב-preload ל-Early Hints – ראו תמיכה בדפדפנים.

השלב השני כולל צמצום הסיכון לשימוש ב-Early Hints במשאבים או במקורות שעשויים להיות מיושנים או שהמשאב הראשי לא משתמש בהם יותר. לדוגמה, יכול להיות שמשאבים שמתעדכנים לעיתים קרובות ויש להם גרסאות (למשל, example.com/css/main.fa231e9c.css) הם לא הבחירה הטובה ביותר. חשוב לזכור שהבעיה הזו לא ספציפית ל-Early Hints, אלא חלה על כל preload או preconnect בכל מקום שבו הם עשויים להופיע. זהו סוג הפרטים שהכי קל לטפל בהם באמצעות אוטומציה או תבניות (לדוגמה, תהליך ידני עלול להוביל לכתובות URL של גרסאות או גיבוב לא תואמות בין preload לבין תג ה-HTML בפועל שמשתמש במשאב).

לדוגמה, נניח את התהליך הבא:

GET /main.html
Host: example.com
User-Agent: [....] Chrome/103.0.0.0 [...]

השרת צופה שיהיה צורך ב-main.abcd100.css ומציע לטעון אותו מראש באמצעות הנחיות מוקדמות:

103 Early Hints
Link: </main.abcd100.css>; rel=preload; as=style
[...]

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

200 OK
[...]
<HTML>
<head>
   <title>Example</title>
   <link rel="stylesheet" href="/main.abcd105.css">

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

<HTML>
<head>
   <title>Example</title>
   <link rel="stylesheet" href="/main.css">
   <link rel="stylesheet" href="/experimental.3eab3290.css">

לבסוף, בצד השרת, מחפשים בקשות למשאבים ראשיים שנשלחות מדפדפנים שידועים כתומכים ב-Early Hints, ומגיבים מיד עם 103 Early Hints. בתגובה 103, צריך לכלול את ההנחיות הרלוונטיות להתחברות מראש ולטעינה מראש. כשהמשאב הראשי יהיה מוכן, יש להמשיך עם התגובה הרגילה (לדוגמה, 200 OK אם הפעולה בוצעה בהצלחה). כדי לשמור על תאימות לאחור, מומלץ לכלול גם כותרות HTTP מסוג Link בתגובה הסופית, ואולי אפילו להוסיף משאבים קריטיים שהתגלו במהלך יצירת המשאב הראשי (לדוגמה, החלק הדינמי של משאב מפתח אם פעלתם לפי ההצעה 'פיצול לשניים'). כך זה נראה:

GET /main.html
Host: example.com
User-Agent: [....] Chrome/103.0.0.0 [...]
103 Early Hints
Link: <https://fonts.google.com>; rel=preconnect
Link: </main.css>; rel=preload; as=style
Link: </common.js>; rel=preload; as=script

כמה רגעים לאחר מכן:

200 OK
Content-Length: 7531
Content-Type: text/html; charset=UTF-8
Content-encoding: br
Link: <https://fonts.google.com>; rel=preconnect
Link: </main.css>; rel=preload; as=style
Link: </common.js>; rel=preload; as=script
Link: </experimental.3eab3290.css>; rel=preload; as=style
<HTML>
<head>
   <title>Example</title>
   <link rel="stylesheet" href="/main.css">
   <link rel="stylesheet" href="/experimental.3eab3290.css">
   <script src="/common.js"></script>
   <link rel="preconnect" href="https://fonts.googleapis.com">

תמיכה בדפדפנים

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

תמיכה בחיבור מראש:

תמיכה בדפדפנים

  • Chrome: ‏ 103.
  • Edge: ‏ 103.
  • Firefox: ‏ 120.
  • Safari: 17.

תמיכה בחיוב מראש:

תמיכה בדפדפנים

  • Chrome: ‏ 103.
  • Edge: ‏ 103.
  • Firefox: ‏ 123.
  • Safari: לא נתמך.

ב-Chrome DevTools יש גם תמיכה ב-103 הנחיות מוקדמות, ואפשר לראות את הכותרות Link במשאבי המסמך:

חלונית &#39;רשת&#39; שמציגה כותרות לרמזים מוקדמים
הכותרות Link של הרמזים המוקדמים מוצגות בכלי הפיתוח ל-Chrome.

הערה: כדי להשתמש במשאבים של Early Hints, אסור לסמן את התיבה Disable cache ב-DevTools כי Early Hints משתמש במטמון הדפדפן. במשאבים שהועלו מראש, הגורם המפעיל יופיע כ-early-hints והגודל יופיע כ-(Disk cache):

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

לצורך כך נדרש גם אישור מהימן לבדיקת HTTPS.

ב-Firefox (החל מגרסה 126) אין תמיכה מפורשת ב-103 Early Hints ב-DevTools, אבל משאבים שנטענים באמצעות Early Hints לא מציגים את פרטי הכותרת של HTTP, וזה אחד מהאינדיקטורים לכך שהם נטענו באמצעות Early Hints.

תמיכה לשרתים

ריכזנו כאן סיכום קצר של רמת התמיכה ב-Early Hints בתוכנות פופולריות של שרתי HTTP בקוד פתוח:

הפעלת הנחיות מוקדמות בדרך הקלה

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

איך להימנע מבעיות אצל לקוחות שלא תומכים ב-Early Hints

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

אם תשלחו רק 103 הנחיות מוקדמות בתגובה ללקוחות ששולחים כותרת בקשת HTTP מסוג sec-fetch-mode: navigate, תוכלו לוודא שהנחיות כאלה יישלחו רק ללקוחות חדשים יותר שמבינים שצריך להמתין לתגובה הבאה. בנוסף, מכיוון שאפשר להשתמש ב-Early Hints רק בבקשות ניווט (ראו ההגבלות הקיימות), היתרון הנוסף הוא שאפשר להימנע משליחת הבקשות האלה ללא צורך בבקשות אחרות.

בנוסף, מומלץ לשלוח את ההצעות המוקדמות רק דרך חיבורי HTTP/2 או HTTP/3, ורוב הדפדפנים יקבלו אותן רק דרך הפרוטוקולים האלה.

דפוס מתקדם

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

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

המגבלות הנוכחיות

ריכזנו כאן את המגבלות של הנחיות מוקדמות כפי שהן מוטמעות ב-Chrome:

  • זמין רק לבקשות ניווט (כלומר, המשאב הראשי של המסמך ברמה העליונה).
  • יש תמיכה רק ב-preconnect וב-preload (כלומר, אין תמיכה ב-prefetch).
  • אם תשלחו Hints מוקדמים ולאחר מכן תשלחו הפניה לדומיין אחר בתגובה הסופית, Chrome יבטל את המשאבים והחיבורים שהשיג באמצעות ה-Hints המוקדמים.
  • משאבים שנטענים מראש באמצעות הנחיות מוקדמות מאוחסנים במטמון ה-HTTP, והדף מאחזר אותם משם בשלב מאוחר יותר. לכן, אפשר לטעון מראש רק משאבים שאפשר לשמור במטמון באמצעות הנחיות מוקדמות, אחרת המשאב ייאוחזר פעמיים (פעם אחת על ידי ההנחיות המוקדמות ופעם נוספת על ידי המסמך). ב-Chrome, המטמון של HTTP מושבת לאישורי HTTPS לא מהימנים (גם אם ממשיכים לטעון את הדף).
  • אי אפשר לטעון מראש תמונות עם תגובה דינמית (באמצעות imagesrcset,‏ imagesizes או media) באמצעות כותרות HTTP מסוג <link>, כי אזור התצוגה לא מוגדר עד ליצירת המסמך. המשמעות היא שאי אפשר להשתמש ב-103 הנחיות מוקדמות כדי לטעון מראש תמונות רספונסיביות, וייתכן שהתמונה הלא נכונה תיטען אם משתמשים בהן למטרה הזו. כאן אפשר לעקוב אחרי הדיון בנושא הצעות לטיפול טוב יותר בבעיה הזו.

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

מה השלב הבא?

בהתאם לעניין בקרב הקהילה, יכול להיות שנוסיף להטמעה של הטיפים המוקדמים את היכולות הבאות:

  • הנחיות מוקדמות למשאבים שלא ניתן לשמור במטמון באמצעות מטמון הזיכרון במקום מטמון ה-HTTP.
  • הנחיות מוקדמות שנשלחות בבקשות למשאבים משניים.
  • הנחיות מוקדמות שנשלחות בבקשות למשאבים הראשיים של iframe.
  • תמיכה ב-prefetch ב-Early Hints.

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

הקשר ל-H2/Push

אם אתם מכירים את התכונה HTTP2/Push שהוצאה משימוש, יכול להיות שתתהו מה ההבדל בין הטיפים המוקדמים לבין התכונה הזו. בעוד שב-Early Hints נדרש מסלול הלוך ושוב כדי שהדפדפן יתחיל לאחזר משאבי משנה קריטיים, ב-HTTP2/Push השרת יכול להתחיל לדחוף משאבי משנה לצד התגובה. זה נשמע נהדר, אבל יש לכך חיסרון מבני משמעותי: ב-HTTP2/Push היה קשה מאוד להימנע משליחת משאבי משנה שכבר היו בדפדפן. האפקט הזה של 'דחיפה מוגזמת' הוביל לשימוש פחות יעיל ברוחב הפס של הרשת, שפגע באופן משמעותי בהטבות הביצועים. באופן כללי, הנתונים מ-Chrome הראו ש-HTTP2/Push גרם בפועל לירידה נטו בביצועים ברחבי האינטרנט.

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

התמונה הממוזערת היא של Pierre Bamin.