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

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

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

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

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

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

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

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

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

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

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

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

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

Largest Contentful Paint (LCP)

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

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

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

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

Cumulative Layout Shift (CLS)

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

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

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

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

סיכום

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