import דינמי ב-ES2020

ייבוא קבצים דינמית באמצעות פונקצית import חדשה.

פיצ׳ר מגניב במיוחד שנכנס ל-ES2020 הוא import דינמי שניתן להשתמש בו גם כ-lazyload.

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

export default class MyModule {
  constructor() {
    this.myText = 'Hello World!';
  }
  sayHello() {
    console.log(this.myText);
  }
}

איך אשתמש בו? משהו בסגנון הזה:

import MyModule from ('/path/to/MyModule.js');
const myModule = new MyModule;
myModule.sayHello();

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

SyntaxError: ... 'import' and 'export' may only appear at the top level.

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

התקן החדש מאפשר לנו להשתמש ב-import כפונקציה בכל חלק של הקוד שלנו. מדובר בפונקציה אסינכרונית שמחזירה לנו פרומיס. אם אתם לא יודעים מה זה פרומיס, במאמר הזה יש הסבר (הגיעה עם תקן ES6) וגם async-await (בתקן ES2017).

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

See the Pen Dynamic import() in action by Ran Bar-Zik (@barzik-the-vuer) on CodePen.

אם יש export ואנו רוצים לקבל אותו, אז זה מה שהפרומיס מחזיר. למשל, הדוגמה הזו מ-MDN:

let module = await import('/modules/my-module.js');

אם התחביר של async await מאיים (והוא לא אמור) אז למשל אפשר להשתמש בו במסגרת פרומיס רגיל. למשל, אם ניקח את מודול הדוגמה שהסברתי עליו בהתחלה – משהו כזה:

import('/path/to/MyModule.js')
  .then((MyModule) => {
    const myModule = new MyModule;
    myModule.sayHello();
  });

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

זה לא פיצ׳ר מורכב, אבל זה בהחלט פיצ׳ר חשוב.

פוסטים נוספים שכדאי לקרוא

פתרונות ומאמרים על פיתוח אינטרנט

יישום של nonce על מנת להגן מפני התקפות injection

בפוסט הקודם הסברתי על hash עם CSP על משאבי inline – שזה נחמד ומעולה אבל פחות ישים בעולם האמיתי שבו בדרך כלל התוכן ה-inline (בין

גלילה לראש העמוד