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

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

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

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

מדידה

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

  1. כדי לראות תצוגה מקדימה של האתר, לוחצים על הצגת האפליקציה. לאחר מכן לוחצים על מסך מלא מסך מלא.
  2. מקישים על 'Control+Shift+J' (או על 'Command+Option+J' ב-Mac) כדי לפתוח את כלי הפיתוח.
  3. לוחצים על הכרטיסייה רשתות.
  4. מסמנים את התיבה Disable cache (השבתת מטמון).
  5. טוענים מחדש את האפליקציה.

חלונית רשת שמוצגת בה חבילת JavaScript בנפח 71.2KB.

JavaScript בנפח 71.2KB רק כדי למיין כמה מספרים באפליקציה פשוטה. מה נותן?

בקוד המקור (src/index.js), הספרייה lodash מיובאת ונעשה בה שימוש. באפליקציה הזו. Lodash מספקת כלים שימושיים רבים אבל רק שיטה אחת מהחבילה משתמשת כאן. להתקנה וייבוא של יחסי תלות שלמים עם צד שלישי, חלק ממנו הוא טעות נפוצה.

אופטימיזציה

יש כמה דרכים לחתוך את גודל החבילה:

  1. כתבו שיטת מיון מותאמת אישית במקום לייבא ספרייה של צד שלישי
  2. שימוש בשיטה המובנית Array.prototype.sort() למיון מספרי
  3. אפשר לייבא את השיטה sortBy רק מ-lodash ולא את הספרייה כולה
  4. כדאי להוריד את הקוד למיון רק כשהמשתמש לוחץ על הלחצן

אפשרות 1 ו-2 הן השיטות המתאימות ביותר להקטנת גודל החבילה יהיה הגיוני ביותר ליישום אמיתי). עם זאת, ההגדרות שלא משתמשים במדריך הזה כדי ללמד 😈.

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

ייבוא רק של מה שצריך

צריך לשנות מספר קבצים כדי לייבא רק את השיטה היחידה מ-lodash. בתור התחלה, צריך להחליף את התלות הזאת ב-package.json:

"lodash": "^4.7.0",

עם זה:

"lodash.sortby": "^4.7.0",

עכשיו ב-src/index.js, מייבאים את המודול הספציפי הזה:

import "./style.css";
import _ from "lodash";
import sortBy from "lodash.sortby";

מעדכנים את אופן המיון של הערכים:

form.addEventListener("submit", e => {
  e.preventDefault();
  const values = [input1.valueAsNumber, input2.valueAsNumber, input3.valueAsNumber];
  const sortedValues = _.sortBy(values);
  const sortedValues = sortBy(values);

  results.innerHTML = `
    <h2>
      ${sortedValues}
    </h2>
  `
});

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

חלונית רשת שמוצגת בה חבילת JavaScript בנפח 15.2KB.

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

פיצול קוד

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

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

  • אחד שאחראי על הקוד שמרכיבים את המסלול הראשוני שלנו
  • מקטע משני שמכיל את קוד המיון שלנו

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

כדי להתחיל, צריך להסיר את הייבוא ברמה העליונה של שיטת המיון ב-src/index.js:

import sortBy from "lodash.sortby";

ומייבאים אותו בתוך ה-event listener שמופעל כשלוחצים על הלחצן:

form.addEventListener("submit", e => {
  e.preventDefault();
  import('lodash.sortby')
    .then(module => module.default)
    .then(sortInput())
    .catch(err => { alert(err) });
});

התכונה import() היא חלק מ הצעה (כרגע בשלב 3 בתהליך TC39) כדי לכלול את היכולת לייבא מודול באופן דינמי. ה-webpack כבר כולל תמיכה בנושא הזה והוא פועל לפי אותו תחביר לפי ההצעה.

import() מחזיר הבטחה, וכשהטיפול מסתיים, נבחר שמפוצל למקטע נפרד. אחרי שהמודול מוחזר, module.default משמש לציון ברירת המחדל קובץ הייצוא שסופק על ידי lodash. ההבטחה כבר קשורה ל.then אחר קוראת ל-method sortInput כדי למיין את שלושת ערכי הקלט. בסוף המשימה שרשרת מובטחת, .catch() משמש לטיפול במקרים שבהם ההבטחה נדחתה עקב שגיאה.

הדבר האחרון שצריך לעשות הוא לכתוב את ה-method sortInput בסוף הקובץ. צריכה להיות פונקציה שמחזירה פונקציה לוקחת בשיטה המיובאת מ-lodash.sortBy. לאחר מכן הפונקציה הפנימית יכולה ממיינים את שלושת ערכי הקלט ומעדכנים את ה-DOM.

const sortInput = () => {
  return (sortBy) => {
    const values = [
      input1.valueAsNumber,
      input2.valueAsNumber,
      input3.valueAsNumber
    ];
    const sortedValues = sortBy(values);

    results.innerHTML = `
      <h2>
        ${sortedValues}
      </h2>
    `
  };
}

מעקב

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

חלונית רשת שמציגה חבילת JavaScript בנפח 2.7KB.

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

חלונית רשת שמציגה חבילת JavaScript בנפח 2.7KB ואחריה חבילת JavaScript בנפח 13.9KB.

שימו לב איך המספרים עדיין ממוינים!

סיכום

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

ממשק משתמש בטעינה מדורגת

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

טעינה מדורגת של מודולים של צמתים של צד שלישי

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

טעינה מדורגת עם framework של JavaScript

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

למרות שמועיל להבין איך פועל ייבוא דינמי, תמיד כדאי להשתמש של framework/הספרייה שמומלצת למודולים ספציפיים לטעינה מדורגת.

טעינה מראש ושליפה מראש (prefetch)

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

טעינה מדורגת של יותר מקוד

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