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

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

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

למה פיצול קוד יכול להועיל?

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

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

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

מדידה

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

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

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

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

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