שליפה מראש (prefetch) של משאבים כדי להאיץ את הניווטים בעתיד

מידע על הטיפים לגבי משאבים מסוג rel=prefetch ואיך משתמשים בהם

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

במדריך הזה נסביר איך לעשות זאת באמצעות <link rel=prefetch>, רמז למשאב שמאפשר ליישם אחסון נתונים לפני אחזור (prefetching) בצורה קלה ויעילה.

שיפור הניווטים באמצעות rel=prefetch

הוספת <link rel=prefetch> לדף אינטרנט מורה לדפדפן להוריד דפים שלמים או חלק מהמשאבים (כמו סקריפטים או קובצי CSS) שהמשתמש עשוי להזדקק להם בעתיד:

<link rel="prefetch" href="/articles/" as="document">

תרשים שמראה איך פועלת שליפה מראש של קישורים.

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

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

תרחישים לדוגמה

שליפה מראש של הדפים הבאים

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

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

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

אחזור מראש של נכסים סטטיים

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

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

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

  • טעינה מראש של תמונות יכולה לקצר משמעותית את זמני ה-LCP של רכיבי תמונה מסוג LCP.
  • אחזור מראש של גיליונות סגנונות יכול לשפר את ה-FCP ואת ה-LCP, כי זמן ההורדה של גיליון הסגנונות מהרשת יימנע. גיליונות סגנונות חוסמים את העיבוד, ולכן הם יכולים לצמצם את ה-LCP כשהם נשלפים מראש. במקרים שבהם רכיב ה-LCP של הדף הבא הוא תמונת רקע של CSS שנשלחה דרך המאפיין background-image, התמונה תאוחזר מראש גם כמשאב תלוי של גיליון הסגנון שאוחזר מראש.
  • אחזור מראש של JavaScript יאפשר את העיבוד של הסקריפט שנאגר מראש הרבה יותר מהר מאשר אם הרשת הייתה צריכה לאחזר אותו קודם במהלך הניווט. יכולה להיות לכך השפעה על אינטראקציה עד התגובה הבאה (INP) בדף. במקרים שבהם ה-Markup מנוהל בצד הלקוח באמצעות JavaScript, אפשר לשפר את ה-LCP על ידי צמצום עיכובי הטעינה של המשאבים, והרינדור של ה-Markup בצד הלקוח שמכיל את רכיב ה-LCP של הדף יכול להתרחש מוקדם יותר.
  • אחזור מראש של גופנים אינטרנטיים שעדיין לא נמצאים בשימוש בדף הנוכחי יכול למנוע שינויים בפריסה. במקרים שבהם נעשה שימוש ב-font-display: swap;, תקופת ההחלפה של הגופן מתבטלת, וכתוצאה מכך הטקסט עובר עיבוד מהיר יותר ומבטל שינויי פריסה. אם דף עתידי ישתמש בגופן שנטען מראש, ורכיב ה-LCP של הדף הוא בלוק של טקסט שמשתמש בגופן אינטרנט, גם זמן ה-LCP של האלמנט הזה יהיה מהיר יותר.

שליפה מראש של מקטעי JavaScript על פי דרישה

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

לדוגמה, אם יש לכם דף שמכיל לחצן שפותח תיבת דו-שיח שמכילה בורר אמוג'י, אתם יכולים לחלק אותו לשלושה קטעי JavaScript – home, ‏ dialog ו-picker. אפשר לטעון את דף הבית ואת תיבת הדו-שיח בשלב הראשון, ואת הבורר אפשר לטעון על פי דרישה. כלים כמו webpack מאפשרים להורות לדפדפן לבצע אחסון מראש של קטעי הקוד האלה על פי דרישה.

איך מטמיעים את rel=prefetch

הדרך הפשוטה ביותר להטמיע את prefetch היא להוסיף תג <link> ל-<head> של המסמך:

<head>
  ...
  <link rel="prefetch" href="/articles/" as="document">
  ...
</head>

המאפיין as עוזר לדפדפן להגדיר את הכותרות הנכונות ולקבוע אם המשאב כבר נמצא במטמון. דוגמאות לערכים של המאפיין הזה: document, script, style, font, image ו-others.

אפשר להתחיל שליפה מראש (prefetch) גם באמצעות כותרת ה-HTTP Link:

Link: </css/style.css>; rel=prefetch

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

אחזור מראש של מודולים של JavaScript באמצעות תגובות קסם של webpack

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

קטע הקוד הבא טוען באופן עצל (lazy) פונקציונליות מיון מהספרייה lodash כדי למיין קבוצת מספרים שתישלח באמצעות טופס:

form.addEventListener("submit", e => {
  e.preventDefault()
  import('lodash.sortby')
    .then(module => module.default)
    .then(sortInput())
    .catch(err => { alert(err) });
});

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

form.addEventListener("submit", e => {
   e.preventDefault()
   import(/* webpackPrefetch: true */ 'lodash.sortby')
         .then(module => module.default)
         .then(sortInput())
         .catch(err => { alert(err) });
});

הקוד הזה מורה ל-webpack להחדיר את התג <link rel="prefetch"> למסמך ה-HTML:

<link rel="prefetch" as="script" href="1.bundle.js">

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

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

אפשר גם להטמיע אחסון מקדים חכם יותר באמצעות ספריות שמשתמשות ב-prefetch ברקע:

גם quicklink וגם Guess.js משתמשים ב-Network Information API כדי להימנע משימוש בהאצה לפני האחזור (prefetching) אם המשתמש נמצא ברשת איטית או שהאפשרות Save-Data מופעלת.

שליפה מראש (prefetch) ברקע

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

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

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

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

סיכום

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