הפחתת מטענים ייעודיים (payloads) של JavaScript באמצעות פיצול קוד

אף אחד לא אוהב לחכות. יותר מ-50% מהמשתמשים נוטשים אתר אם הטעינה שלו נמשכת יותר מ-3 שניות.

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

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

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

בהתאם לארכיטקטורה של האתר – במיוחד אם האתר מסתמך במידה רבה על עיבוד בצד הלקוח – הפחתת הגודל של עומסי העבודה של JavaScript שאחראים לעיבוד ה-Markup עשויה להוביל לשיפור זמני Largest Contentful Paint‏ (LCP). מצב כזה יכול להתרחש אם הדפדפן מתעכב בזיהוי המשאב של LCP עד לסיום הטיפול בסימון בצד הלקוח, או אם הפעילות בשרשור הראשי עמוסה מדי כדי לרנדר את אלמנט ה-LCP הזה. שני התרחישים האלה עלולים לעכב את זמן ה-LCP של הדף.

מדידה

מערכת Lighthouse מציגה ביקורת שנכשלה אם נדרשת כמות זמן משמעותית כדי להריץ את כל ה-JavaScript בדף.

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

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

חבילות מודולים פופולריות כמו webpack,‏ Parcel ו-Rollup מאפשרות לפצל את החבילות באמצעות ייבוא דינמי. לדוגמה, קטע הקוד הבא מציג דוגמה ל-method‏ someFunction שמופעל כששולחים טופס.

import moduleA from "library";

form
.addEventListener("submit", e => {
  e
.preventDefault();
  someFunction
();
});

const someFunction = () => {
 
// uses moduleA
}

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

form.addEventListener("submit", e => {
  e
.preventDefault();
 
import('library.moduleA')
   
.then(module => module.default) // using the default export
   
.then(() => someFunction())
   
.catch(handleError());
});

const someFunction = () => {
   
// uses moduleA
}

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

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

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