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

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

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

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

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

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

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

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

השוואה בין שני אתרים.
לפני/אחרי השוואת הרמזים המוקדמים באתר בדיקה שבוצעה באמצעות WebPageTest (Moto G4 – DSL)

איך להשתמש ברמזים מוקדמים

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

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

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

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

השלב השני כולל צמצום הסיכון לשימוש ברמזים מוקדמים לגבי משאבים או מקורות שעשויים להיות מיושנים או שכבר לא נמצאים בשימוש במשאב הראשי. לדוגמה, יכול להיות שמשאבים שמתעדכנים בתדירות גבוהה ויש בהם גרסאות (לדוגמה, example.com/css/main.fa231e9c.css) לא יהיו האפשרות הכי טובה. חשוב לשים לב שהדאגה הזו לא ספציפית לרמזים מוקדמים, היא חלה על כל 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 הזה מתעדכן לעיתים קרובות, והמשאב הראשי כבר קיים חמש גרסאות (abcd105) יותר ממשאב ה-CSS החזוי (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">

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

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

תמיכה בדפדפן

  • 103
  • 103
  • 120
  • 17

תמיכה בטעינה מראש:

תמיכה בדפדפן

  • 103
  • 103
  • 123
  • x

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

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

הערה: כדי להשתמש במשאבים של רמזים מוקדמים, אין לסמן את Disable cache בכלי הפיתוח כי 'רמזים מוקדמים' משתמשים במטמון של הדפדפן. במשאבים שנטענים מראש, מאתחל יוצג בתור early-hints, והגודל יוצג כך: (Disk cache):

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

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

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

תמיכה לשרתים

הנה סיכום קצר של רמת התמיכה ב-EAPs (רמזים מוקדמים) בתוכנות שרת HTTP פופולריות של תוכנת קוד פתוח:

הפעלת רמזים מוקדמים בדרך קלה יותר

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

איך למנוע בעיות עבור לקוחות שלא תומכים ברמזים מוקדמים

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

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

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

דפוס מתקדם

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

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

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

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

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

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

מה השלב הבא?

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

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

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

הקשר ל-H2/Push

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

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

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