תוספים ב-Babel

מהם תוספים, איך משתמשים בהם וב-preset שמאגד אותם ביחד.
Babel Logo

בכל המאמרים האחרונים שבהם דיברנו על Babel, הראינו איך ממירים ג'אווהסקריפט מ-ES6 ל-ES5, על מנת לעשות את זה, ביקשנו שה-preset יהיה 2015. עולה השאלה מה זה ה-preset הזה, מאיפה הוא בא? בשביל זה אנחנו חייבים לדבר על תוספים. plugin בלעז. בואו נתעלם לשניה מה-preset ונדמיין שהוא לא קיים ואנו חיים בעולם של תוספים בלבד.

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

בואו ונניח שיש לי את הקוד הבא:


let myData = {
	name: 'Moshe',
	debt: '200'
}
let content = `Hi ${myData.name}, You owe me ${myData.debt} USD.`;
document.getElementById('container').textContent = content;

אם אני ארצה להמיר את הטמפלייטינג, אני אוריד את התוסף template literals transform באמצעות:

npm install babel-plugin-transform-es2015-template-literals

ה-babelrc. שלי יראה כך:


{
  "plugins": ["transform-es2015-template-literals"]
}

כשאני אריץ את babel דרך הקונסולה/CMD (זוכרים איך?) –

./node_modules/.bin/babel src -d lib -w

איך הקובץ המקומפל יראה? הוא יראה כך:


let myData = {
	name: 'Moshe',
	debt: '200'
};
let content = 'Hi ' + myData.name + ', You owe me ' + myData.debt + ' USD.';
document.getElementById('container').textContent = content;

יש פה שני דברים מעניינים מאוד – הדבר הראשון הוא שאנחנו רואים שהטמפלייטינג הומר בהצלחה. אין לנו שימוש בסוגריים המסולסלים ובגרשיים ` ההפוכים. הדבר השני הוא שה-let לא הומר! למה הוא לא הומר? כי אני לא משתמש בתוסף שממיר אותו. התוסף הזה נקרא block scoping transform והוא ידאג להמיר את let או const למשהו שסביבה ישנה יותר תדע להסתדר איתו – ה-var הישן והטוב!

איך מתקינים? בדיוק כמו התוסף הקודם – יש הוראות מדויקות בדוקומנטציה של Babel שמכילה את כל התוספים. אבל בקצרה:

npm install babel-plugin-transform-es2015-block-scoping

וב-babelrc אנחנו נציין אותו בצורה מפורשת יחד עם התוסף השני:


{
  "plugins": [
	"transform-es2015-template-literals", 
	"transform-es2015-block-scoping"
	]
}

נריץ במהירות שוב את ה-Babel דרך שורת הפקודה ונראה שהקובץ המקומפל המיר את ה-let וכמובן גם את הטמפלייטינג:


var myData = {
	name: 'Moshe',
	debt: '200'
};
var content = 'Hi ' + myData.name + ', You owe me ' + myData.debt + ' USD.';
document.getElementById('container').textContent = content;

עכשיו זה נראה בדיוק כמו שרצינו.

מה הבעיה עם התוספים? בעוד שהם מאפשרים קסטומיזציה מאוד גבוהה, בטח ובטח כאשר נגיע לתקנים מתקדמים יותר. זה יכול להיות מעייף לציין כל תוסף ותוסף. הרי ב-ES6 (שידוע גם כ-ES2015, זוכרים?) יש המון תוספות ושינויים וזה עוד לפני הפוליפילים! בדיוק בשביל זה יש לנו את ה-preset! מדובר באוסף של תוספים. במקום לבוא ולציין רשימה של 21 תוספים שמכסים את ES2015, אני פשוט יכול לבוא ולומר – תביא לי את כל התוספים שימירו את כל ES2015 לES5. איך אני עושה את זה? אני מתקין את preset 2015 באמצעות:

npm install --save-dev babel-preset-es2015

ומוסיף ל-babel את ההגדרות:


{
  "presets": ["es2015"]
}


אני כבר לא צריך לציין את כל התוספים שקשורים ל-ES2015, כשאני כותב preset, זה כמו לציין את כל התוספים האלו:

check-es2015-constants
transform-es2015-arrow-functions
transform-es2015-block-scoped-functions
transform-es2015-block-scoping
transform-es2015-classes
transform-es2015-computed-properties
transform-es2015-destructuring
transform-es2015-duplicate-keys
transform-es2015-for-of
transform-es2015-function-name
transform-es2015-literals
transform-es2015-modules-commonjs
transform-es2015-object-super
transform-es2015-parameters
transform-es2015-shorthand-properties
transform-es2015-spread
transform-es2015-sticky-regex
transform-es2015-template-literals
transform-es2015-typeof-symbol
transform-es2015-unicode-regex
transform-regenerator

עכשיו אנחנו יודעים מה זה preset2015. יש כמובן גם preset2016 ו-preset2017 ויהיו עוד. כל ה-preset והתוספים שהם כוללים נמצאים בדוקומנטציה של Babel.

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

ב-ES2017, זה חוקי לחלוטין לכתוב משהו כזה:


function myFunc(arg1, arg2,) {
	console.log(arg1, arg2);
}

myFunc('Hello', 'World',); 

שימו לב לפסיק בסוף. זה דבר שיפיל כל דפדפן או סביבה שלא תומכת ב-trailing commas in function syntax – שזה נכון לכתיבת שורות אלו כמעט הכל. אבל אם יש לי Babel, אני לא צריך לדאוג. אני רואה בדוקומנטציה שיש תוסף ל-syntax-trailing-function-commas והוא חלק מה-preset של 2017. אני אתקין את ה-preset כך:

npm install --save-dev babel-cli babel-preset-es2017

לא אשכח להוסיף את preset2017 ל-preset2015 שיש כבר ב-babelrc. שלי:


{
  "presets": ["es2015", "es2017"]
}

ואריץ את כל הסיפור הזה כפי שאנו מכירים כבר באמצעות שורת הפקודה:

./node_modules/.bin/babel src -d lib -w

הנה הקוד לפני הקימפול – יש בו גם ES2015 וגם ES2017:


let content = `Hi ${myData.name}, You owe me ${myData.debt} USD.`;
document.getElementById('container').textContent = content;

function myFunc(arg1, arg2,) {
	console.log(arg1, arg2);
}

myFunc('Hello', 'World',); 

ה-ES2015 בא לכדי ביטוי בטמפלייטינג וב-let וה-ES2017 בא לכדי ביטוי באמצעות הפסיק בסוף רשימת הארגומנטים בהגדרת הפונקציה ובקריאה לפונקציה. קוד כזה ייכשל כמעט בכל דפדפן שהוא, נכון לכתיבת השורות ובטח ובטח בכל סביבת node שהיא. אבל מייד אחרי הרצת הקימפול, אני אקבל את הקוד הזה:


'use strict';

var content = 'Hi ' + myData.name + ', You owe me ' + myData.debt + ' USD.';
document.getElementById('container').textContent = content;

function myFunc(arg1, arg2) {
	console.log(arg1, arg2);
}

myFunc('Hello', 'World');

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

יש לנו עוד כמה presets – למשל latest שתכיל גם את ES2015, ES2016 ו-ES2017 ויש גם presets 'לא רשמיים' של Babel שאנשים הכינו. בסופו של דבר, preset זה אוסף של תוספים. ותוסף כל אחד יכול לכתוב.

מה קורה אם אני משתמש ב-preset שמכיל תוסף שציינתי ב-plugin? או בתוסף שכבר נמצא ב-plugin? ב-Babel הקימפול הוא לפי הסדר. תוסף אחד ממיר מה שהוא יכול ומעביר לתוסף הבא וכך הלאה. הסדר ב-Babel בגרסה 6.5 שהיא הגרסה העדכנית – הולך ככה – קודם התוספים – מהראשון לאחרון ואז ה-presets מהאחרון לראשון.

שימו לב שהעניינים מתחילים להתחמם כשאנחנו מדברים על פיצ'רים ממש ממש חדשים ב-ECMAScript. לא חייבים לחכות שהתקן יתקבע. כל הצעה חדשה של התקן עוברת ארבעה שלבים (stages) –

שלב 0 – רעיון בלבד.
שלב 1 – הצעה ממשית.
שלב 2 – טיוטה וספק (spec) ראשוני.
שלב 3 – מועמד לכניסה לתקן.
שלב 4 – נכנס לתקן.

כאשר מגבשים תקן חדש, כמו למשל ES017 (ובעתיד אלו שיבואו אחריו), חלק גדול מהתקן הוא בשלב 0 וחלקים אחרים הם בשלבים אחרים. יש גם להם presets משלהם. אם תשתמשו ב preset stage 0 תוכלו כבר עכשיו להשתמש בתוספות/שינויים לתקן שעדיין לא נכנסו גם לסביבות המתקדמות ביותר. זה כמובן על אחריותכם.

יש עוד מה להרחיב על Babel – איך משתמשים בו עם grunt למשל, או עם gulp או עם webpack, אבל אלו כבר מאמרים שמתאימים יותר למדריכים אחרים. אם אתם יודעים להשתמש ב-Babel בקונסולה/CMD, תדעו להשתמש בו גם כחלק מבילד שבסופו של דבר עושה אבסטרקציה לשורת הפקודה הזו.

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

תמונה מצוירת של רובוט שמנקה HTML
יסודות בתכנות

סניטציה – למה זה חשוב

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

בינה מלאכותית

Safeguards על מודל שפה גדול (LLM)

פוסט בשילוב עם פודקאסט וסרטון על ההגנות שאפשר להציב על LLM בסביבת פרודקשן

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