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

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

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

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

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

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

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 במשורה ולמדוד את ההשפעה בעולם האמיתי.