במודול הקודם, תיאוריה מסוימת שמאחורי נתיב העיבוד הקריטי ואיך משאבים לחסימת רינדור וחסימת ניתוח יכולים לעכב לעיבוד הראשוני של הדף. עכשיו אתם מבינים חלק מהתיאוריה תהיו מוכנים ללמוד כמה טכניקות לאופטימיזציה של בנתיב העיבוד.
כשהדף נטען, ב-HTML יש הפניה למשאבים רבים שמספקים דף עם המראה והפריסה שלו באמצעות CSS, וגם האינטראקטיביות באמצעות JavaScript. במודול הזה, נדון בכמה מושגים חשובים שקשורים במאמר הזה נפרט את המשאבים האלה ואת האופן שבו הם משפיעים על זמן הטעינה של דף.
עיבוד החסימה
כמו שהסברנו במודול הקודם, CSS הוא משאב render-blocking, מכיוון שהיא מונעת מהדפדפן לעבד תוכן כלשהו עד מודל האובייקט של CSS (CSSOM) בנוי. הדפדפן חוסם את העיבוד כדי למנוע הבהוב של תוכן ללא עיצוב (FOUC), דבר לא רצוי מבחינת חוויית המשתמש.
בסרטון הקודם יש FOUC קצר שבו אפשר לראות את הדף בלי בכל עיצוב. לאחר מכן, כל הסגנונות מוחלים ברגע ש-CSS של הדף הסתיימה הטעינה מהרשת, והגרסה ללא עיצוב של הדף מוחלפת מיד בגרסה הסגנון.
באופן כללי, FOUC הוא משהו שבדרך כלל לא רואים, אבל העיקרון חשוב להבין, כדי שתוכלו לדעת למה הדפדפן חוסם את העיבוד של הדף עד להורדה והחלה של שירות CSS על הדף. עיבוד החסימה לא בהכרח לא רצוי, אבל כדאי לצמצם את משך הזמן עד לשמור על אופטימיזציה של שירות ה-CSS.
חסימת מנתח נתונים
משאב חוסם מנתח מפריע למנתח ה-HTML, למשל <script>
ללא מאפייני async
או defer
. כשהמנתח נתקל
<script>
, הדפדפן צריך לבדוק ולהריץ את הסקריפט לפני
להמשיך בניתוח של שאר קוד ה-HTML. זה מתוכננות, כי סקריפטים עלולים
לשנות את ה-DOM או לגשת אליו במהלך התקופה שבה הוא עדיין נמצא בבנייה.
<!-- This is a parser-blocking script: -->
<script src="/script.js"></script>
כשמשתמשים בקובצי JavaScript חיצוניים (בלי async
או defer
), המנתח
חסימת הקובץ מהרגע שבו הקובץ אותר ועד שמורידים אותו, מנותחים אותו,
בוצעה. כשמשתמשים ב-JavaScript מוטבע, המנתח חסום באופן דומה עד
הסקריפט המוטבע מנותח ומופעל.
סורק הטעינה מראש
סורק הטעינה מראש הוא אופטימיזציה של דפדפן בצורת HTML משני
כלי לניתוח שסורק את תגובת ה-HTML הגולמית כדי למצוא ולאחזור באופן ספקולטיבי
לפני שמנתח ה-HTML הראשי יגלה אותם, אחרת. עבור
לדוגמה, סורק הטעינה מראש יאפשר לדפדפן להתחיל להוריד
המשאב שצוין ברכיב <img>
, גם כשמנתח ה-HTML חסום
בזמן אחזור ועיבוד של משאבים כמו CSS ו-JavaScript.
כדי לנצל את סורק הטעינה מראש, צריך לכלול משאבים קריטיים בתגי העיצוב של HTML שהשרת שלח. הדפוסים הבאים של טעינת משאבים אינו גלוי על ידי סורק הטעינה מראש:
- התמונות נטענות על ידי שירות ה-CSS באמצעות המאפיין
background-image
. התמונות האלה ההפניות נמצאות ב-CSS ולא ניתן לגלות אותן באמצעות סורק הטעינה מראש. - סקריפטים שנטענים באופן דינמי בתור תגי עיצוב של רכיב
<script>
שהוחדרו ל-DOM באמצעות JavaScript או מודולים שנטענו באמצעותimport()
דינמי. - HTML שעבר רינדור אצל הלקוח באמצעות JavaScript. תגי עיצוב כאלה נמצאים בתוך מחרוזות במשאבי JavaScript, ולא ניתן לגלות אותן באמצעות הטעינה מראש בסורק של Google.
- הצהרות
@import
של CSS.
הדפוסים האלה של טעינת משאבים הם משאבים שזוהו בשלב מאוחר, ולכן
לא יפיקו תועלת מסורק הטעינה מראש. מומלץ להימנע מהן ככל האפשר. אם המיקום
אי אפשר להימנע מדפוסים כאלה, אבל ייתכן שתוכלו להשתמש
רמז preload
כדי למנוע עיכובים בגילוי המשאבים.
CSS
שירות CSS קובע את התצוגה והפריסה של הדף. כפי שתואר קודם, שירות CSS הוא משאב חוסם רינדור, ולכן ביצוע אופטימיזציה של ה-CSS על זמן הטעינה הכולל של הדף.
הקטנה
הקטנת קובצי CSS מקטינה את גודל הקובץ של משאב CSS, ולכן הם מהר יותר. ניתן להשיג זאת בעיקר על ידי הסרת תוכן קובץ CSS המקורי, כמו רווחים ותווים נסתרים אחרים, ויצירת פלט את התוצאה של קובץ חדש שעבר אופטימיזציה:
/* Unminified CSS: */
/* Heading 1 */
h1 {
font-size: 2em;
color: #000000;
}
/* Heading 2 */
h2 {
font-size: 1.5em;
color: #000000;
}
/* Minified CSS: */
h1,h2{color:#000}h1{font-size:2em}h2{font-size:1.5em}
בצורתה הבסיסית ביותר, הקטנה של CSS היא אופטימיזציה יעילה לשפר את ה-FCP של האתר, ואולי אפילו את ה-LCP במקרים מסוימים. כלים כמו Bunders יכולים לבצע את האופטימיזציה הזו באופן אוטומטי בשבילכם בסביבת הייצור לבנות.
הסרת שירות CSS שלא נמצא בשימוש
לפני עיבוד תוכן, הדפדפן צריך להוריד ולנתח את כל התוכן גיליונות סגנונות. הזמן שנדרש להשלמת הניתוח כולל גם סגנונות לא בשימוש בדף הנוכחי. אם אתם משתמשים ב-bundler שמשלב את כל שירותי ה-CSS למשאבים בקובץ יחיד, סביר להניח שהמשתמשים שלכם יורידו יותר שירותי CSS שנדרשים כדי לעבד את הדף הנוכחי.
כדי לאתר שירות CSS שלא נמצא בשימוש של הדף הנוכחי, אפשר להשתמש בכלי הכיסוי ב-Chrome כלי פיתוח.
להסרה של שירות CSS שאינו בשימוש יש השפעה כפולה: בנוסף להפחתת ההורדה אתם מבצעים אופטימיזציה לבנייה של עץ רינדור, כי הדפדפן צריך לעבד פחות כללי CSS.
הימנעות מהצהרות @import
CSS
זה אמנם נראה נוח, אבל כדאי להימנע מהצהרות @import
ב-CSS:
/* Don't do this: */
@import url('style.css');
בדומה לאופן הפעולה של הרכיב <link>
ב-HTML, ההצהרה @import
ב-CSS מאפשר לייבא משאב חיצוני של CSS מתוך גיליון סגנונות.
ההבדל העיקרי בין שתי הגישות האלה הוא שרכיב ה-HTML <link>
הוא חלק מתגובת ה-HTML, ולכן התגלה הרבה לפני כן
הורדת את הקובץ באמצעות הצהרה של @import
.
הסיבה לכך היא שכדי שהצהרת @import
תאושר
התגלתה, יש להוריד תחילה את קובץ ה-CSS שמכיל אותו. הזה
התוצאה היא מה שמכונה שרשרת בקשות, שבמקרה של CSS, מעכבת
כמה זמן לוקח לדף להופיע בפעם הראשונה. חיסרון נוסף הוא
לא ניתן לגלות גיליונות סגנונות שנטענו באמצעות הצהרת @import
באמצעות
לטעון מראש, ובכך להפוך למשאבים שחוסמים עיבוד להתגלות מאוחר יותר.
<!-- Do this instead: -->
<link rel="stylesheet" href="style.css">
ברוב המקרים, אפשר להחליף את @import
באמצעות
רכיב <link rel="stylesheet">
. רכיבי <link>
מאפשרים ליצור גיליונות סגנונות
שהורדו בו-זמנית ומפחיתים את זמן הטעינה הכולל, בניגוד ל-@import
שמורידות גיליונות סגנונות ברציפות.
מוטבע של CSS קריטי
הזמן שלוקח להוריד קובצי CSS יכול להגדיל את ה-FCP של דף. פנימי
סגנונות קריטיים במסמך <head>
מבטל את בקשת הרשת ל
משאב CSS, ואם עושים זאת בצורה נכונה, יכולים לשפר את זמני הטעינה הראשונית כאשר
המטמון של הדפדפן של המשתמש אינו מוגדר. אפשר לטעון את שירות ה-CSS הנותר
באופן אסינכרוני, או בסוף הרכיב <body>
.
<head>
<title>Page Title</title>
<!-- ... -->
<style>h1,h2{color:#000}h1{font-size:2em}h2{font-size:1.5em}</style>
</head>
<body>
<!-- Other page markup... -->
<link rel="stylesheet" href="non-critical.css">
</body>
החיסרון, הטמעה של כמות גדולה של CSS מוסיפה עוד בייטים תגובת HTML. מכיוון שמשאבי HTML לעתים קרובות לא ניתן לשמור במטמון זמן רב מאוד - או הכול – המשמעות היא ששירות ה-CSS שהוזן לא נשמר במטמון לדפים הבאים שעשויים להשתמש באותו CSS בגיליונות סגנונות חיצוניים. בדיקה ומדידה של התוכן בדף כדי להבטיח שההתפשרות שווה את המאמץ.
הדגמות של שירות CSS
JavaScript
JavaScript מניע את רוב האינטראקטיביות באינטרנט, אבל הוא כרוך בתשלום. משלוח יותר מדי JavaScript עלול להאט את התגובה של דף האינטרנט במהלך נטענות ואפילו עלולות לגרום לבעיות רספונסיביות שמאטות אינטראקציות – גם שעלולות לגרום לתסכול בקרב המשתמשים.
JavaScript חוסם עיבוד
כשטוענים רכיבי <script>
ללא המאפיינים defer
או async
,
הדפדפן חוסם את הניתוח והרינדור עד להורדה ולניתוח של הסקריפט,
בוצעה. באופן דומה, סקריפטים מוטבעים חוסמים את המנתח עד לניתוח הסקריפט
ולהוציא לפועל.
async
מול defer
async
ו-defer
מאפשרים לסקריפטים חיצוניים להיטען בלי לחסום את ה-HTML
המנתח בעוד שסקריפטים (כולל סקריפטים מוטבעים) עם type="module"
שנדחו באופן אוטומטי. עם זאת, יש כמה הבדלים בין async
לבין defer
שחשוב להבין.
סקריפטים שנטענים באמצעות async
מנותחים ומופעלים מיד לאחר ההורדה,
בזמן שסקריפטים שנטענים עם defer
מבוצעים כשניתוח מסמך HTML
הסתיים — הפעולה מתרחשת באותו זמן כמו האירוע DOMContentLoaded
של הדפדפן.
בנוסף, async
סקריפטים עשויים לפעול בסדר שונה, בעוד defer
סקריפטים
מופעלות לפי הסדר שבו הן מופיעות בתגי העיצוב.
רינדור בצד הלקוח
באופן כללי, עליך להימנע משימוש ב-JavaScript כדי לעבד תוכן קריטי אלמנט ה-LCP של הדף. התהליך הזה נקרא רינדור בצד הלקוח, וזו שיטה נמצא בשימוש נרחב באפליקציות דף יחיד (SPA).
תגי עיצוב שעברו רינדור על ידי JavaScript עוקפים את סורק הטעינה מראש, בתור המשאבים שבתגי העיצוב שמעובדים על ידי הלקוח אינם ניתנים לגילוי. הזה עלול לעכב את ההורדה של משאבים חיוניים, כמו תמונת LCP. בדפדפן מתחיל להוריד את תמונת ה-LCP רק אחרי שהסקריפט מופעל, ומוסיף של הרכיב ל-DOM. מצד שני, ניתן להריץ את הסקריפט רק לאחר שהם גילו, הורדו ונותחו. הפעולה הזו נקראת בקשה קריטית שרשרת ויש להימנע ממנה.
בנוסף, יש סיכוי גבוה יותר שעיבוד תגי עיצוב באמצעות JavaScript ייצור משימות ארוכות לעומת תגי עיצוב שהורדו מהשרת בתגובה לניווט בקשה. שימוש נרחב ברינדור של HTML בצד הלקוח עלול להשפיע לרעה זמן אחזור של אינטראקציה. הדבר נכון במיוחד במקרים שבהם ה-DOM של דף גדול מאוד, מה שמפעיל תהליך רינדור משמעותי כש-JavaScript משתנה את ה-DOM.
הקטנה
בדומה ל-CSS, הקטנת JavaScript מקטינה את גודל הקובץ של משאב סקריפט. דבר זה עשוי להוביל להורדות מהירות יותר, ולאפשר לדפדפן לעבור של ניתוח והידור של JavaScript במהירות רבה יותר.
בנוסף, הקטנה של JavaScript הולכת צעד אחד יותר מאשר הקטנה נכסים אחרים, כמו CSS. כש-JavaScript מוקטן, הוא לא נמחק רק של דברים כמו רווחים, כרטיסיות ותגובות, אבל סמלים שבמקור קובצי JavaScript מקוצרים. התהליך הזה נקרא לפעמים חריג. שפת תרגום לראות את ההבדל, השתמשו בקוד המקור הבא של JavaScript:
// Unuglified JavaScript source code:
export function injectScript () {
const scriptElement = document.createElement('script');
scriptElement.src = '/js/scripts.js';
scriptElement.type = 'module';
document.body.appendChild(scriptElement);
}
כשקוד המקור של JavaScript הקודם מוצג, התוצאה עשויה להיראות משהו כמו קטע הקוד הבא:
// Uglified JavaScript production code:
export function injectScript(){const t=document.createElement("script");t.src="/js/scripts.js",t.type="module",document.body.appendChild(t)}
בקטע הקודם, אפשר לראות שהמשתנה הקריא (לבני אדם)
הערך scriptElement
במקור מקוצר ל-t
. כשמחילים אותו על מודל גדול
של סקריפטים, החיסכון יכול להיות משמעותי, מבלי להשפיע
את התכונות שמספק ה-JavaScript בסביבת הייצור של אתר אינטרנט.
אם אתם משתמשים ב-bundler כדי לעבד את קוד המקור של האתר, בדרך כלל מתבצעת באופן אוטומטי לגרסאות build בסביבת הייצור. מרעננים-כמו Terser, לדוגמה - ניתנים להגדרה ברמה גבוהה, מה שמאפשר לך לתקן התוקפנות של אלגוריתם ההיקש כדי להשיג חיסכון מקסימלי. עם זאת, בדרך כלל ברירות המחדל של כל כלי כוונון מספיקות כדי לגרום התראה האיזון הנכון בין גודל פלט ושימור יכולות.
הדגמות של JavaScript
בוחנים את הידע
מהי הדרך הטובה ביותר לטעון כמה קובצי CSS בדפדפן?
@import
של שירות ה-CSS.<link>
.מה עושה סורק הטעינה מראש של הדפדפן?
<link rel="preload">
בתוך
משאב HTML.
מדוע הדפדפן חוסם באופן זמני את ניתוח ה-HTML כברירת מחדל כאשר מוריד את משאבי JavaScript?
השלב הבא: סיוע לדפדפן באמצעות רמזים לגבי משאבים
עכשיו, אחרי שהבנתם איך משאבים נטענים ברכיב <head>
להשפיע על טעינת הדף הראשונית ועל מדדים שונים, הגיע הזמן להתקדם. ב
נלמד על רמזים למשאבים, ואיך הם יכולים לספק רמזים חשובים
הדפדפן כדי להתחיל לטעון משאבים ולפתוח חיבורים למקורות שונים
מוקדם יותר מאשר הדפדפן היה עושה זאת בלעדיהם.