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

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

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

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

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

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

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

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

ביקורת של 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

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

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

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

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

ההשפעות של טעינה מראש על Core Web Vitals

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

Largest Contentful Paint (LCP)

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

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

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

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

Cumulative Layout Shift (CLS)

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

  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 כשמדובר בגופני אינטרנט. כמו תמיד, כדאי לערוך ניסויים במעבדה, אבל להסתמך על נתונים מהשטח כדי לקבוע אם אסטרטגיות טעינת הגופנים משפרות את ה-CLS או פוגעות בו.

מהירות התגובה לאינטראקציה באתר (INP)

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

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

סיכום

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