6

I'm learning enormous JavaScript ecosystem and I can't understand the following.

Babel is a transpiler, and from the official website:

Babel is a toolchain that is mainly used to convert ECMAScript 2015+ code into a backwards compatible version of JavaScript in current and older browsers or environments.

Since I use the @babel/preset-env present, I assume that this should be enough to write ES6+ code and get it transpiled to some compatible code, according to my browserslist.

Then, I came into this: https://babeljs.io/docs/en/babel-polyfill, which suggest using @babel/polyfill instead of:

import "core-js/stable";
import "regenerator-runtime/runtime";

Instead of the deprecated @babel/polyfill. Now I know what a polyfill is, I used the Intersection Observer polyfill, for example.

So my question is: is this something "automatic" that Babel provides? Some sort of plugin that can polyfill my code, automatically? What are the two libraries that they are talking about? why I need these two additional packages in order to make my code ES5-compatible, if Babel should do it by itself? Consider Object.assign: it will work in IE11 only with core-js package. Why Babel didn't transpiled it?

EDIT: my mistake reading the article, but my question remains the same.

gremo
  • 47,186
  • 75
  • 257
  • 421
  • Actually, that page says that "As of Babel 7.4.0, this package (babel/polyfill) has been deprecated", and says you *should* use those imports. – Heretic Monkey May 13 '20 at 20:13
  • Yes, but It says that I should use @abel/polyfill. – gremo May 13 '20 at 20:14
  • regenerator-runtime is the supporting runtime for polyfilling generators from regenerator released by Facebook. This was back when async/await was a new concept to Javascript and generators weren't available yet. Note copyright 2013: http://facebook.github.io/regenerator/ – user120242 May 13 '20 at 20:14
  • No, it doesn't say you should use babel/polyfill. The big alert at the top of the page, with the alarm image in it, says the package is deprecated, meaning no one should use it any more (if they are using versions of Babel later than 7.4.0). It leaves the text explaining how to use it, since there are people out there who have not upgraded past Babel 7.4.0 and therefore can't take advantage of the other polyfills. – Heretic Monkey May 13 '20 at 20:18
  • Don't the docs tell you that you only need to use those things if you have to support IE or something? I remember that being the case like over 5 years ago. And then all the complaints about breaking code because of the renaming of the polyfill, but it being mostly an issue of people "doing it wrong(r)" – user120242 May 13 '20 at 20:36

3 Answers3

11

Both polyfill and transpilation enable you to use new features in old environments (think of old vs new browsers for example), the main difference is that a polyfill does that by implementing the feature in the old environment itself. So if we go by ES6 ES5 terminology, polyfill enables you to use a new feature by implementing it in ES5, however some new features can never be implemented in ES5, think for example about the arrow syntax introduced by ES6 - this is where transpilation is needed.

An example where transpilation is needed is arrow syntax (() => {}) because you can never implement that in ES5, and an example where a polyfill can be used is if you wanted to implement the String.prototype.includes method. That can be implemented like this:

// taken from mdn
if (!String.prototype.includes) {
  String.prototype.includes = function(search, start) {
    'use strict';

    if (search instanceof RegExp) {
      throw TypeError('first argument must not be a RegExp');
    } 
    if (start === undefined) { start = 0; }
    return this.indexOf(search, start) !== -1;
  };
}

Now another important distinction is that a polyfill will use the native feature if it exists, however transpilation will not. That leads to the conclusion that polyfills should be preferred over transpilation, because of security and performance reasons.

Last distinction is that transpilation is about language syntax, while polyfill is about language syntax and native browser APIs.

Long story made short: transpilation is at compile time, while polyfill is at runtime.

Now that the distinction has been made clear, we can see that to use new code and features Babel uses both strategies. The main guideline is to use polyfill when possible; otherwise, transpilation (transpilation will be needed for a new syntax that can never be implemented in the old ES5 environment, itself). So you need to import core-js to polyfill features that could have been enabled by transpilation, but its better to implement them using polyfill.

Let's take some code as an example, to differentiate between the two:

const f = (str) => {
  return str.includes('fun')
}

what Babel will do is transpile that code into something like the following:

var f = function f() {
 // notice that `.includes()` stays. Even though this is
 // an ES6 feature, it stays because
 // Babel does not transpile it.
 // 
 // the following code will break if you don't import
 // a polyfill using core-js or any other polyfill library
 return str.includes('fun');
}

I have cut a lot of what Babel transpilation output would be, if you want to see it you can read here.

And now to your question if Babel uses something automatic to do that. The answer is yes, and that is @babel/preset-env, which will configure the transpilation processes and polyfills needed for you automatically based on your target environment.

heyitsalec
  • 192
  • 4
  • 19
ehab
  • 7,162
  • 1
  • 25
  • 30
  • Thanks for the long and crafted explanation. I made a mistake reading the article (actually suggesting to leave `@babel/polyfill`), but my question remains. If Babel transpile my code back to ES5, why do I need `core-js` in order to make `Object.assign` available in IE11? Babel should transform that to something running in a browser that doesn't support it. What I'm missing? – gremo May 14 '20 at 19:22
  • @gremo i have edited my answer to more direct in answering your question – ehab May 14 '20 at 21:17
1

Babel only provides the language manipulation (i.e. the syntax), not the underlying types of objects needed (i.e. the nouns acted on).

Daniel A. White
  • 187,200
  • 47
  • 362
  • 445
0

ES6 provides more than just new syntax it also adds new functionality like for example:

Number.isInteger(num) checks whether num is an integer (a number without a decimal fraction).

What's new in ES6?

Marco
  • 7,007
  • 2
  • 19
  • 49