אינטרנט ישראל
  • ראשי
  • אודות רן בר-זיק ואינטרנט ישראל
  • ערוץ טלגרם
  • מסטודון
  • התחברו אלי בטוויטר
  • התחברו אלי בלינקדאין
  • ספר ג'אווהסקריפט
  • ראשי
  • אודות רן בר-זיק ואינטרנט ישראל
  • ערוץ טלגרם
  • מסטודון
  • התחברו אלי בטוויטר
  • התחברו אלי בלינקדאין
  • ספר ג'אווהסקריפט
ראשי » מדריכים » Babel » Babel Polyfills

Babel Polyfills

רן בר-זיק פברואר 12, 2017 7:07 am אין תגובות

מתי, איך ולמה משתמשים בפוליפילים כדי לאפשר אובייקטים ותכונות מתקדמות גם לסביבות מיושנות

למאמר הקודם על BabelBabel – יצירת sourcemap וקובץ הגדרות
למאמר הבא על Babelתוספים ב-Babel
כדאי תמיד להשאר מעודכנים! אם יש לכם טלגרם, בדקו את ערוץ הטלגרם של האתר שבו אני מעדכן על פוסטים חדשים 🙂 אם אתם רוצים ללמוד תכנות באופן מקיף ומסודר, הצטרפו לאלפי הלומדים בפרויקט "ללמוד ג'אווהסקריפט בעברית" שמלמד לתכנת בג'אווהסקריפט, ב-Node.js ובריאקט וגם מלמד על תרומה לקוד פתוח. גם ספרים דיגיטליים וגם ספרים מודפסים. בשיתוף הקריה האקדמית אונו ובתמיכת חברות מובילות כגון Wix, Outbrain, Elementor, Iron Source, Chegg, Really Good ועוד.

לא כל הפיצ'רים של ES6 נולדו שווים, חלק מהפיצ'רים הם בבחינת סוכר סינטקסי – כלומר השפה השתנה על מנת שיהיה יותר קל לקרוא ולכתוב את הקוד. חלק מהפיצ'רים האחרים ניתנים לשכתוב על ידי ES5. אפילו גנרטורים. אם תציצו באתר ES6 features בחלק של גנרטורים, תוכלו לראות שניתן להמיר את הקוד של גנרטורים לקוד של ES5.
המצב מסתבך עם פיצ'רים כמו promise או weakMaps שלא ניתן לשכפלם בשום פנים ואופן ב-ES5. למה? כשאנו כותבים Promise למשל, אנחנו מניחים שיש אובייקט גלובלי שקוראים לו Promise. גם WeakMap עובדת כך. אם אנו מניחים מתודות סטטיטיות באובייקטים – כמו Object.assign.
במקרה הזה, אם אני אנסה לקמפל את הקוד של Promise ב-Babel, אני אראה שהוא מתקמפל אבל ה-Promise נשאר, מה שיגרום לשגיאה בוודאות בדפדפנים או ב-node מגרסה v1.2.0 ומטה.

בוא ונסתכל על הקוד החביב הזה שכתוב ב-ES6 – מדובר בקוד שאנחנו כבר מכירים


let myPromise = new Promise(function(resolve, reject) {
  let request = new XMLHttpRequest();

  request.open('GET', 'http://api.icndb.com/jokes/random');
  request.onload = function() {
    if (request.status == 200) {
      resolve(request.response); // we got data here, so resolve the Promise
    } else {
      reject(Error(request.statusText)); // status is not 200 OK, so reject
    }
  };

  request.onerror = function() {
    reject(Error('Error fetching data.')); // error occurred, reject the  Promise
  };

  request.send(); //send the request
});

myPromise.then(function(data) {
  console.log('Got data! Promise fulfilled.');
  document.getElementById('container').textContent = JSON.parse(data).value.joke;
}, function(error) {
  console.log('Promise rejected.');
  document.getElementById('container').textContent = 'Sorry, something wrong. please refresh';
  console.log(error.message);
}) 

יש בו let ויש בו Promise, אם נקמפל אותו עם Babel ועם ES2015 preset שאמור לקחת את כל הפיצ'רים של ES6 ולהמיר אותם ל-ES5 נראה שהקוד המקומפל נראה כך (הדגשתי את מה שחשוב) :


'use strict';

var myPromise = new Promise(function (resolve, reject) {
  var request = new XMLHttpRequest();

  request.open('GET', 'http://api.icndb.com/jokes/random');
  request.onload = function () {
    if (request.status == 200) {
      resolve(request.response);
    } else {
      reject(Error(request.statusText));
    }
  };

  request.onerror = function () {
    reject(Error('Error fetching data.'));
  };

  request.send();
});

myPromise.then(function (data) {
  console.log('Got data! Promise fulfilled.');
  document.getElementById('container').textContent = JSON.parse(data).value.joke;
}, function (error) {
  console.log('Promise rejected.');
  document.getElementById('container').textContent = 'Sorry, something wrong. please refresh';
  console.log(error.message);
});

הקימפול העיף את ההערות ושינה את let ל-var אבל לא נגע ב-Promise! למה?

התשובה היא שכאן מדובר באובייקט גלובלי ודרך הטיפול של Babel בפיצ'רים גלובליים היא מעט שונה ותלויה בר אם אני עובד עם Babel בדפדפן או ב-node (וגם שם יש כמה דרכים לטפל בזה). הדרך שאותה אסקור כאן היא Polyfills. פוליפילים זה קטעי ג'אווהסקריפט שמכניסים פונקציונליות חדשה לגמרי לדפדפנים או לסביבות הרצה. למשל, ב-CSS היינו משתמשים בעבר בפוליפילים שידמו פינות עגולות או פיצ'רים של HTML5 באקספלורר מצחין דפדפנים מיושנים אלו ואחרים.

פוליפיל הוא פשוט קטע קוד בג'אווהסקריפט שמדמה פונקציה אינהרנטית בדפדפנים מיושנים. הפוליפיל של Promise בודק אם יש את האובייקט הגלובלי Promise במידה וכן, סימן שהדפדפן/סביבת ההרצה תומכת ב-Promise. במידה ולא, הוא יוצר את האובייקט הגלובלי Promise ומכניס לתוכו את כל הפונקציונליות שאמורה להיות שם – למשל את המתודות resolve, then ו-reject והכל ב-ES5 תקני למהדרין. כך שגם דפדפנים/סביבות שלא מכירים כלל ES6, ידעו מה לעשות איתו. זה רץ פחות טוב מן הסתם מ-Promise טבעי, אבל זה רץ.

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

npm install --save-dev babel-polyfill

ועושים include באופן הבא:




אם אתם משתמשים ב-node, זה אפילו יותר קל, פשוט מבצעים require ממש איך שהקוד מתחיל לרוץ. אם אתם משתמשים ב-node באופן נאיבי, פשוט צריך לדאוג שזה ירוץ ב-entry point הראשון שלכם:


require("babel-polyfill");

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

נשמע פשוט, נכון? אבל צריך לזכור כמה דברים:

הפוליפיל חייב לרוץ קודם

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

var promise = new Promise(function(resolve, reject) {
                   ^
ReferenceError: Promise is not defined

סימן שיש קריאה ל-Promise לפני שהוא רץ.

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

פוליפיל מכניס אובייקט/מתודות גלובליים

הפוליפיל מכניס promise גלובלי (או אובייקטים גלובליים אחרים). זה עלול לגרום לבעיה משמעותית אם יש מודול אחר או קטע קוד אחר שמטפל בו. אם אתם כותבים פלגין/מודול, אל תניחו שיש אובייקט Promise גלובלי אלא השתמשו ב-babel-plugin-transform-runtime – שזה תוסף של Babel. במאמר הבא אסביר באופן מפורט על תוספים

נושא הפוליפילים עלול לבלבל, מי שמתבלבל – פשוט צריך לזכור להכניס את הפוליפיל של Babel אם הוא משתמש ב-promises או באובייקטים גלובליים אחרים ולהשתמש בכל הפיצ'רים שהוא רוצה בלי לחשוש. מי שלא מפחד להיכנס קצת לעומק – צריך לבדוק במה הוא משתמש ולבצע את השמת הפוליפילים באמצעות core-js או בדרכים אחרות. ברוב המקרים, על מנת לתמוך בסביבות ישנות יותר, אנחנו נכניס את Babel polyfill לאפליקציה שלנו ונשכח ממנה.

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

כדאי תמיד להשאר מעודכנים! אם יש לכם טלגרם, בדקו את ערוץ הטלגרם של האתר שבו אני מעדכן על פוסטים חדשים 🙂 אם אתם רוצים ללמוד תכנות באופן מקיף ומסודר, הצטרפו לאלפי הלומדים בפרויקט "ללמוד ג'אווהסקריפט בעברית" שמלמד לתכנת בג'אווהסקריפט, ב-Node.js ובריאקט וגם מלמד על תרומה לקוד פתוח. גם ספרים דיגיטליים וגם ספרים מודפסים. בשיתוף הקריה האקדמית אונו ובתמיכת חברות מובילות כגון Wix, Outbrain, Elementor, Iron Source, Chegg, Really Good ועוד.
כל המאמרים בסדרת המדריכים על Babel
Babel ECMAScript 6

השארת תגובה

ביטול

ללמוד ג'אווהסקריפט בעברית

ללמוד לתכנת ג'אווהסקריפט בעברית שגייס יותר משלוש מאות אלף שקל ולמעלה מ-2000 תומכים - בואו ללמוד עכשיו איך לתכנת.

רשימת הנושאים
  • מדריכים
    • ריאקט
    • טייפסקריפט
    • ECMAScript 6
    • ES20XX
    • Node.js
    • Express
    • רספברי פיי
    • Babel
    • docker
    • MongoDB
    • Git
    • לימוד MySQL
    • SASS
    • jQuery
    • CSS3
    • HTML 5
    • SVN
    • LESS
  • פיתוח אינטרנט
    • פתרונות ומאמרים על פיתוח אינטרנט
    • jQuery Scripts
    • jQuery למתקדמים
    • יסודות בתכנות
    • נגישות אינטרנט
  • חדשות אינטרנט
  • מידע כללי על אינטרנט
    • רשת האינטרנט
    • בניית אתרי אינטרנט
  • rss logo

    לכל המאמרים

    לכל המאמרים שפורסמו באינטרנט ישראל משנת 2008 ועד עכשיו.
  • rss logo

    RSS Feed

    משתמשים בקורא RSS? אם כן, עקבו אחרי אינטרנט ישראל באמצעות פיד ה-RSS!
    מה זה RSS?
  • Twitter logo

    עקבו אחרי בטוויטר

    בחשבון הטוויטר שלי אני מפרסם עדכונים מהירים על חדשות בתחום התכנות והיזמות, התרעות על מצבי חירום ורכילות בוערת על תחום הווב.
    מה זה טוויטר?
  • facebook like image

    ערוץ הטלגרם של אינטרנט ישראל

    בערוץ הטלגרם של אינטרנט ישראל אני מפרסם את הפוסטים של באתר וכן עדכונים טכנולוגיים נוספים.
    מה זה טלגרם?
  • github logo

    הפרויקטים שלי בגיטהאב

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

כל הזכויות שמורות לרן בר-זיק ולאינטרנט ישראל | מדיניות הפרטיות של אתר אינטרנט ישראל | אתר אינטרנט ישראל נגיש לפי תקן WCAG 2.0 AA | הצהרת הנגישות של האתר | אבטחת מידע ודיווח על בעיית אבטחת מידע

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