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

כשפותחים דף אינטרנט, הדפדפן מבקש מהשרת את מסמך ה-HTML, מנתח את התוכן שלו ושולח בקשות נפרדות לכל המשאבים שאליהם מתבצעת ההפניה. כמפתח, אתם כבר מכירים את כל המשאבים שהדף שלכם צריך, ואילו מהם הם החשובים ביותר. אפשר להשתמש בידע הזה כדי לבקש מראש את המשאבים הקריטיים ולזרז את תהליך הטעינה. בפוסט הזה מוסבר איך לעשות זאת בעזרת <link rel="preload">.

איך פועלת הטעינה מראש

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

צילום מסך של החלונית ל-Chrome DevTools Network.
בדוגמה הזו, הגופן Pacifico מוגדר בגיליון הסגנון באמצעות כלל @font-face. הדפדפן טוען את קובץ הגופן רק אחרי שההורדה והניתוח של גיליון הסגנונות הושלמו.

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

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

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

בדיקת בקשות למפתחות טעינה מראש ב-Lighthouse.

כדי לטעון מראש משאבים, אפשר להוסיף תג <link> עם המזהה rel="preload" לראש מסמך ה-HTML:

<link rel="preload" as="script" href="critical.js">

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

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

טעינות מראש שלא נמצאות בשימוש גורמות להצגת אזהרה במסוף ב-Chrome, כ-3 שניות אחרי האירוע load.

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

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

משאבים לטעינה מראש שמוגדרים ב-CSS

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

טעינה מראש של קובצי CSS

אם משתמשים בגישת ה-CSS הקריטית, צריך לפצל את ה-CSS לשני חלקים. ה-CSS הקריטי שנדרש לעיבוד התוכן בחלק העליון והקבוע מופיע ב-<head> של המסמך, ו-CSS שאינו קריטי נטען בדרך כלל באופן מדורג עם JavaScript. המתנה להרצת JavaScript לפני טעינת CSS שאינו קריטי עלולה לגרום לעיכובים בעיבוד כשהמשתמשים גוללים, ולכן כדאי להשתמש ב-<link rel="preload"> כדי להתחיל את ההורדה מוקדם יותר.

טעינה מראש של קובצי JavaScript

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

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

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

<head>
  <link rel="preload" as="script" href="critical.js">
</head>

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

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

<link rel="preload" href="ComicSans.woff2" as="font" type="font/woff2" crossorigin>

רכיבי <link> מקבלים גם מאפיין type, המכיל את סוג ה-MIME של המשאב המקושר. הדפדפנים משתמשים בערך של המאפיין type כדי לוודא שהמשאבים נטענים מראש רק אם סוג הקובץ שלהם נתמך. אם הדפדפן לא תומך בסוג המשאב שצוין, הוא יתעלם מה-<link rel="preload">.

אפשר גם לטעון מראש כל סוג של משאב באמצעות כותרת ה-HTTP Link:

Link: </css/style.css>; rel="preload"; as="style"

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

טעינה מראש של מודולים של JavaScript באמצעות Webpack

אם אתם משתמשים ב-Module Bundler שיוצר קובצי build של האפליקציה, צריך לבדוק אם הוא תומך בהחדרת תגים של טעינה מראש. ב-webpack בגרסה 4.6.0 ואילך, יש תמיכה בטעינה מראש באמצעות תגובות קסם בתוך import():

import(_/* webpackPreload: true */_ "CriticalChunk")

אם משתמשים בגרסה ישנה יותר של Webpack, משתמשים בפלאגין של צד שלישי, כמו preload-webpack-plugin.

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

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

Largest Contentful Paint (LCP)

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

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

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

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

Cumulative Layout Shift (CLS)

Cumulative Layout Shift (CLS) הוא מדד חשוב במיוחד כשמדובר בגופני אינטרנט, ול-CLS יש אינטראקציה משמעותית עם גופנים באינטרנט שמשתמשים במאפיין CSS של font-display לניהול אופן הטעינה של הגופנים. כדי לצמצם את השינויים בפריסה שקשורה לגופן האינטרנט, כדאי להשתמש בשיטות הבאות:

  1. טעינה מראש של גופנים תוך שימוש בערך ברירת המחדל block של font-display. זהו איזון עדין. חסימת תצוגה של גופנים ללא חלופה יכולה להיחשב כבעיה בחוויית המשתמש. מצד אחד, טעינת גופנים באמצעות font-display: block; מבטלת שינויים בפריסה שקשורים לגופן האינטרנט. מצד שני, עדיין תרצו לטעון את גופן האינטרנט הזה בהקדם האפשרי אם הם חיוניים לחוויית המשתמש. שילוב של טעינה מראש עם font-display: block; עשוי להיות פשרה מקובלת.
  2. טעינה מראש של גופנים תוך שימוש בערך fallback של font-display. fallback הוא סיכון בין swap ל-block, בכך שתקופת החסימה שלו קצרה מאוד.
  3. צריך להשתמש בערך optional של font-display ללא טעינה מראש. אם גופן אינטרנט אינו חיוני לחוויית המשתמש, אבל הוא עדיין משמש לעיבוד כמות משמעותית של טקסט בדף, מומלץ להשתמש בערך optional. בתנאים שונים, המערכת של optional תציג את הטקסט בדף בגופן חלופי בזמן שהוא טוען את הגופן ברקע בניווט הבא. התוצאה נטו בתנאים האלה היא CLS משופר, כי גופנים של המערכת יעובדו באופן מיידי, בעוד שטעינות לאחר מכן ייטענו את הגופן באופן מיידי, ללא שינויי פריסה.

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

אינטראקציה עד הצבע הבא (INP)

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

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

סיכום

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