Codelab: טעינה מראש של נכסים קריטיים כדי לשפר את מהירות הטעינה

ב-Codelab הזה, הביצועים של דף האינטרנט הבא ישופרו על ידי טעינה מראש ושליפה מראש של כמה משאבים:

צילום מסך של האפליקציה

מדידה

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

  • כדי לראות תצוגה מקדימה של האתר, מקישים על View App ואז על Fullscreen מסך מלא.

מפעילים את בדיקת הביצועים של Lighthouse (Lighthouse > אפשרויות > ביצועים) בגרסה הפעילה של התקלה (מידע נוסף זמין גם במאמר איך לגלות הזדמנויות לשיפור הביצועים באמצעות Lighthouse).

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

Lighthouse: בדיקה של בקשות מפתח לטעינה מראש
  • לוחצים על 'Control+Shift+J' (או 'Command+Option+J' ב-Mac) כדי לפתוח את כלי הפיתוח.
  • לוחצים על הכרטיסייה רשתות.
חלונית רשת עם משאב שהתגלה לאחרונה

הקובץ main.css לא אוחזר על ידי רכיב קישור (<link>) שמוצב במסמך ה-HTML, אבל קובץ JavaScript נפרד, fetch-css.js, מצרף את הרכיב Link ל-DOM אחרי האירוע window.onLoad. המשמעות היא שהקובץ מאוחזר רק אחרי שהדפדפן מסיימים לנתח ולהפעיל את קובץ ה-JS. באופן דומה, גופן אינטרנט (K2D.woff2) שצוין בתוך main.css מאוחזר רק אחרי שההורדה של קובץ ה-CSS תסתיים.

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

├─┬ / (initial HTML file)
  └── fetch-css.js
    └── main.css
      └── K2D.woff2

מכיוון שקובץ ה-CSS נמצא ברמה השלישית של שרשרת הבקשות, מערכת Lighthouse זיהתה אותו כמשאב שהתגלה לאחרונה.

טעינה מראש של משאבים קריטיים

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

הוסף תג טעינה מראש לאפליקציה זו:

<head>
  <!-- ... -->
  <link rel="preload" href="main.css" as="style">
</head>

המאפיין as משמש לזיהוי סוג המשאב שמאוחזר, ו-as="style" משמש לטעינה מראש של קובצי גיליון סגנונות.

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

חלונית רשת עם משאב שנטען מראש

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

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

<head>
  <!-- ... -->
  <link rel="preload" href="main.css" as="style">
  <link rel="preload" href="details.css" as="style">
</head>

טוענים מחדש את האפליקציה ובודקים את החלונית רשת. מוצגת בקשה לאחזר את details.css על אף שדף האינטרנט לא משתמש בו.

חלונית רשת עם טעינה מראש מיותרת

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

אזהרה על טעינה מראש במסוף

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

<head>
  <!-- ... -->
  <link rel="preload" href="main.css" as="style">
  <link rel="preload" href="details.css" as="style">
</head>

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

שליפה מראש (prefetch) של משאבים עתידיים

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

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

מסלול פרטים

קובץ CSS נפרד, details.css, מכיל את כל הסגנונות הנדרשים לדף הפשוט הזה. כדי לאחזר מראש את המשאב הזה, צריך להוסיף רכיב קישור ל-index.html.

<head>
  <!-- ... -->
  <link rel="prefetch" href="details.css">
</head>

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

השבתת המטמון בכלי הפיתוח ל-Chrome

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

חלונית רשת עם משאב שנשלף מראש

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

בקשות רשת של דף פרטים

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

בקשה לפרטים אוחזרה מהמטמון של הדיסק

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

טעינה מראש ושליפה מראש (prefetch) עם Webpack

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

אפליקציית ממיין הקסם שמדגימה פיצול קוד

אפשר לגשת לתקלה באפליקציה הזו.

קטע הקוד הבא, שנמצא ב-src/index.js,, אחראי לייבוא הדינמי של השיטה כשלוחצים על הלחצן.

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

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

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

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

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

חלונית הרכיבים עם תג לשליפה מראש (prefetch)

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

חלונית רשת עם בקשה שאוחזרה מראש

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

import(/* webpackPreload: true */ 'module')

סיכום

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

לסיכום:

  • כדאי להשתמש בטעינה מראש למשאבים שמגלים מאוחר אבל הם חיוניים לדף הנוכחי.
  • כדאי להשתמש בשליפה מראש (prefetch) של משאבים שדרושים למסלול ניווט עתידי או לפעולה עתידית.

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

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