What’s a Babel?

In the official Babel documentation, this is how Babel is described

Babel is a JavaScript compiler that converts ECMAScript 2015+ code into backward-compatible JavaScript syntax so that it can run in current and older browsers and other environments. In a nutshell,Babel’s job is to:

  • The syntax conversion
  • JS source conversion
  • Add missing features to the target environment by using a Polyfill

Babel fundamentals

The basic principle of Babel is to transform the source code into an abstract syntax tree, then process the abstract syntax tree to generate a new syntax tree, and finally generate new JS code from the new syntax tree. The whole compilation process can be divided into three stages:

Parsing –>transforming –>generating

Note :Babel is only responsible for compiling new syntax introduced under new standards, such as Class,Array Function, and ES Instead of compiling new methods and apis for native objects, such as array.includes,Map,Set, etc., these are solved by ployfill.

Babel basic use

Basic environment to run Babel

1. Babel/cli or Babel/node

npm install i -S @babel/cli
Copy the code

@babel/ CLI is a built-in command-line tool provided by Babel. @babel/cli is installed in a project, while @babel/node is installed globally.

2.@babel/core

npm install i -S @babel/core
Copy the code

If @babel/cli is installed and you execute Babel test.js in the project directory, you will find that @babel/core is not found, because @babel/cli relies on @babel/core to generate AST. Therefore, you need to install @babel/core after installing @babel/ CLI.

Command not found: Not found: Not found: Not found: Not found This is because @babel/cli is installed under the project, not globally. Therefore, you cannot use the Babel command directly. You need to add the following configuration item in the package.json file:

"scripts": {
   "babel":"babel"
 }
Copy the code

At this point, the code still cannot be encoded because the corresponding plug-in or preset needs to be installed to compile the file.

Configuration file.babelrc

The configuration file for Babel is.babelrc and is stored in the project root directory. The first step in using Babel is to configure this file.

This file is used to set transcoding rules and plug-ins. The basic format is as follows.

{
  "presets": [],
  "plugins": []
}
Copy the code

The presets field sets transcoding rules. The following rule sets are provided officially and you can install them as needed.

$NPM install --save-dev babel-preset- ES2015 # react presets $NPM install --save-dev babel-preset- preset-react # ES7 transcoding rules for syntax proposals in different stages (there are four stages), Select a $NPM install --save-dev babel-preset-stage-0 $NPM install --save-dev babel-preset-stage-1 $NPM install --save-dev babel-preset-stage-2 $ npm install --save-dev babel-preset-stage-3Copy the code

Then, add these rules to.babelrc.

  {
    "presets": [
      "es2015",
      "react",
      "stage-2"
    ],
    "plugins": []
  }
Copy the code

The plug-in

Plug-ins are used to define how to transform your code. Babel will load the NPM package in node_modules and compile the syntax for the plugin.

.babelrc

{
  "plugins": ["transform-decorators-legacy", "transform-class-properties"]
}
Copy the code

Plug-in execution sequence

The plug-in executes before the preset

Plug-ins are executed from left to right. That is, in the example above, Babel calls the transform methods defined in the transform-decorators-Legacy plug-in first, and then the transform-class-Properties methods when it does the AST traversal.

The plug-in and transfer

Parameters are an array of plug-in names and parameter objects.

{
    "plugins": [
        [
            "@babel/plugin-proposal-class-properties", 
            { "loose": true }
        ]
    ]
}
Copy the code

The preset

A preset is a combination of plugins to achieve a certain translation capability, such as @babel/preset-react used in React, which is a combination of the following plugins.

@babel/plugin-syntax-jsx @babel/plugin-transform-react-jsx @babel/plugin-transform-react-display-name

We can also manually configure a series of plugins in our plugins to do this, like this:

{
  "plugins":["@babel/plugin-syntax-jsx","@babel/plugin-transform-react-jsx","@babel/plugin-transform-react-display-name"]
}
Copy the code

But this is not so elegant on the one hand, on the other hand, it increases the user’s difficulty. If you use the preset, it will be much fresher

{
  "presets":["@babel/preset-react"]
}
Copy the code

The default order of execution

As mentioned earlier, plug-ins are executed from left to right, and the default execution order is the exact opposite, right to left

As mentioned earlier, plugins are executed from left to right, and the default execution order is the exact opposite, right to left {"presets": ["a", "b", "c"]}Copy the code

It executes in THE order C, B, A, which is a little odd, mostly to ensure backward compatibility, since most users put “ES2015” before “stage-0”.

Polyfill

Polyfill translates to “gasket.” A gasket is a way to smooth out the differences between different browser environments so that everyone is the same.

By default, Babel only converts new JavaScript syntax, not new apis, such as Iterator, Generator, Set, Maps, Proxy, Reflect, Symbol, Promise, and other global objects. And some methods defined on global objects (such as object.assign) are not transcoded.

For example, ES6 adds the array. from method to Array objects. Babel does not transcode this method. If you want this method to work, you must use babel-polyfill to provide a spacer for the current environment.

The installation command is as follows.

$ npm install --save babel-polyfill
Copy the code

Note that @babel/polyfill is not configured in the Babel configuration file, but is introduced in our code.

import '@babel/polyfill'; Const arrFun = ()=>{} const arr = [1,2] console.log(arr.includes(1)) promise.resolve (true)Copy the code

The compiled:

require("@babel/polyfill");
var arrFun = function arrFun() {};
var arr = [1, 2, 3];
console.log(arr.includes(1));
Promise.resolve(true);
Copy the code

This should work well in older browsers.

I don’t know if you’ve seen a problem here, but require(“@babel/polyfill”) loads the entire @babel/polyfill in, but in this case we need to deal with Array. Includes and promises. If this results in a larger packet volume, it is obviously not an optimal solution. If only it could load on demand. Actually, Babel had a plan for us

Load useBuiltIns on demand

Let’s go back to @babel/preset-env, the purpose of his appearance is to realize national unity, even the stage-x is dead, why did he leave out the Polyfill feature? The useBuiltIns parameter is provided in the configuration item of @babel/preset-env. As long as the useBuiltIns parameter is used when @babel/preset-env is used, Babel will automatically Polyfill at compilation time. There is no need to manually introduce @babel/ Polyfill into your code, and it can be loaded on demand

Note that you need to configure the version number of Corejs, and if you don’t configure a compilation alert.

UseBuiltIns mechanism parameters:

False: Polyfill will not be loaded on demand if @babel/ Polyfill is introduced. All code will be imported

Usage: Polyfill is performed based on the browser compatibility configuration and the API you use in your code, enabling on-demand loading

Entry: It will be loaded on demand depending on the browser compatibility configuration and the API you use in your code. However, you need to manually import ‘@babel/ Polyfill’ in the entry file.

Code reuse of helper functions

@babel/ plugin-transform-Runtime allows Babel to reuse helper functions during compilation, thus reducing the size of the package.

npm install --save-dev @babel/plugin-transform-runtime
npm install --save @babel/runtime
Copy the code

Configure the Babel:

{
    "presets": [
        [
            "@babel/preset-env",
            {
                "useBuiltIns": "usage",
                "corejs": 3
            }
        ]
    ],
    "plugins": [
       "@babel/plugin-transform-runtime"
    ]
}
Copy the code