This article has participated in the “Digitalstar Project” and won a creative gift package to challenge the creative incentive money.

This post was originally posted on my blog.

1. Introduction

Update 2021-10-18: A sample repository has been added on Github, which works better with it.

What’s a Babel?

Babel is a toolchain for converting ECMAScript 2015+ version code into backwardly compatible JavaScript syntax so it can run in current and older versions of browsers or other environments.

The Chinese word for Babel is the Tower of Babel. In the Bible, there are stories like this. When the people of the earth spoke the same language, when they left the East, they came to the land of Shinar. There, the people managed to make bricks so that they could build a city and a tower to the sky to spread their fame before they were scattered all over the world. When God came to earth and saw the city and the tower, he said that there was nothing that could not be done by a group of people who spoke only one language; So God broke up their language so that they could not understand each other, and scattered them all over the world, and the building of the city stopped. The city was called Babel, and the tower was the Tower of Babel.

You can think of Babel as a unity of languages. Babel, as its author calls it, has a certain amount of ambition. He is to want to present different JS language specifications, unified into one, to achieve compatibility under different browsers.

Babel has also been updated many times by now. This article will focus on the [email protected] version to understand Babel use.

What does Babel do?

There are three common functions:

  1. Syntax conversion. For instance, willes6The arrow function is converted to a normal function compatible with lower versions of browsers.
  2. throughPolyfillWay to add missing features to the target environment (through@babel/polyfillModules).
  3. Source code conversion. Such as the conversiontypescript,jsxAnd so on.

Understand the steps

We’ll walk you through the use of Babel step by step through CLI, plugins, Presets, and polyfill.

The preparatory work

  • Create a directory.
  • performyarn init -y.
  • createsrcDirectory.
  • insrcCreate the entry filemain.js.

The contents of the main.js file are as follows:

// 1.arrow function
const arrowFun = () = > {
  console.log('arrow-function'.this)}// 2.class
class Person {
  constructor() {
    this.name = name
  }
  say() {
    alert('hello')}}// 3. Promise es6 new
const promise = new Promise((resolve, reject) = > {
  setTimeout(() = > {
    if (Math.random() * 10> =5) {
      resolve('greater than 5')}else {
      reject('less than 5')}},2000)})// 4.async await es7
async function fn() {
  try {
    const result = await promise
    console.log(result)
  } catch(err) {
    console.warn('error', err)
  }
  console.log('--- after promise ---')
}

fn()

// 5.includes
const flag = [1.2.3].includes(1)
console.log('includes', flag)
Copy the code

These examples are created for a reason. The current directory results are as follows:

. ├ ─ ─ package. Json ├ ─ ─ the SRC │ └ ─ ─ the main, js └ ─ ─ yarn. The lockCopy the code

What follows is based on that project.

2.CLI

Scaffolding @babel/cli

Babel serves as a conversion tool. It comes with its own set of scaffolding tools.

Create a new project and execute:

yarn add @babel/cli -D
Copy the code

Starting with the [email protected] version, Babel will place all of its official packages in the @babel namespace. This is not unique to Babel. Rather, NPM is an optimization of its own package management. Babel just complied by the way.

In this case, we can use the Babel command line. Because of the environment variables, let’s configure package.json (you can also use NPX instead). Use NPM to execute Babel:

{
  "scripts": {
    "compiler": "babel './src/main.js' --out-dir dist"}}Copy the code

When the YARN compiler is executed, Babel logically translates main.js from SRC into dist.

But now that the YARN Compiler is executed, the code in the dist/main.js file shows no signs of conversion.

2. Core library @babel/core

The core functions of Babel are contained in the @babel/core module. Installation:

yarn add @babel/core -D
Copy the code

If yarn Compiler is executed, the code will still not be converted.

@babel/core can be thought of as a core transformation module function whose execution depends on the options configuration. If there are no options, then this function does nothing.

function core (code, options = []) {
  options.forEach(item= > {
    code += item
  })
  return code
}
Copy the code

These options correspond to plugins in Babel.

3. Plugins plugins

Install the plug-in for the down-conversion arrow function:

yarn add @babel/plugin-transform-arrow-functions -D
Copy the code

Add the command to scripts in package.json:

{
  "scripts": {
    "compiler:plugin": "babel './src/main.js' --out-dir dist --plugins=@babel/plugin-transform-arrow-functions"}}Copy the code

Execute YARN Compiler :plugin again and you will find that the arrows in main.js have been converted:

var _this = this;

// 1.arrow function
const arrowFun = function () {
  console.log('arrow-function', _this);
};
Copy the code

4. The default presets

Presets are simply collections of plugins. There are officially four sets of presets:

  • @babel/preset-env
  • @babel/preset-flow
  • @babel/preset-react
  • @babel/preset-typescript

Where @babel/preset-env represents the preset for the environment. Now we use –presets instead of –plugins.

{
  "scripts": {
    "compiler:preset": "babel './src/main.js' --out-dir dist --presets=@babel/preset-env"}}Copy the code

Run yarn Compiler :preset. You’ll notice that the code has been converted to ES5 code (except for the @babel/polyfill syntax). Promise, etc.)

ReferenceError: regeneratorRuntime is not defined. This is because the actual running of async await also requires @babel/polyfill.

The code can be seen below.

In the absence of a specified browser target, @babel/ Preset -env converts all ES2015-ES2020 code to ES5 compatibility. However, using @babel/preset-env in this way is not recommended, as it does not take advantage of features specific to a particular environment/version.

"use strict";

var _this = void 0;

function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { Promise.resolve(value).then(_next, _throw); }}function _asyncToGenerator(fn) { return function () { var self = this, args = arguments; return new Promise(function (resolve, reject) { var gen = fn.apply(self, args); function _next(value) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value); } function _throw(err) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err); } _next(undefined); }); }; }

function _classCallCheck(instance, Constructor) { if(! (instanceinstanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); }}function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); }}function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }

// 1.arrow function
var arrowFun = function arrowFun() {
  console.log('arrow-function', _this);
}; 

// 2.class
var Person = /*#__PURE__*/function () {
  function Person() {
    _classCallCheck(this, Person);

    this.name = name;
  }

  _createClass(Person, [{
    key: "say".value: function say() {
      alert('hello'); }}]);returnPerson; } ();// 3. Promise es6 new
var promise = new Promise(function (resolve, reject) {
  setTimeout(function () {
    if (Math.random() * 10> =5) {
      resolve('greater than 5');
    } else {
      reject('less than 5'); }},2000);
});

// 4.async await es7
function fn() {
  return _fn.apply(this.arguments);
}

function _fn() {
  _fn = _asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee() {
    var result;
    return regeneratorRuntime.wrap(function _callee$(_context) {
      while (1) {
        switch (_context.prev = _context.next) {
          case 0:
            _context.prev = 0;
            _context.next = 3;
            return promise;

          case 3:
            result = _context.sent;
            console.log(result);
            _context.next = 10;
            break;

          case 7:
            _context.prev = 7;
            _context.t0 = _context["catch"] (0);
            console.warn('error', _context.t0);

          case 10:
            console.log('--- after promise ---');

          case 11:
          case "end":
            return _context.stop();
        }
      }
    }, _callee, nullThe [[0.7]]);
  }));
  return _fn.apply(this.arguments);
}
fn(); 

// 5.includes
var flag = [1.2.3].includes(1);
console.log('includes', flag); 
Copy the code

5. To summarize

This chapter focuses on what you need to install to quickly use Babel.

  • @babel/cliOfficial scaffolding.
  • @babel/core, core conversion module.
  • @babel/pluginsor@babel/presetsSpecific conversion rules.
  • @babel/polyfillPutty is required for earlier versions of browsers. However,babelThere have been new uses to compensate@babel/polyfillExisting disadvantages.

We’ll take a step-by-step look at it later.

3.config files

In the previous chapter, THE YARN Compiler :plugins and YARN Compiler: Presets are configured directly on the command line.

It’s not elegant, and it’s not friendly. So before you understand plugins and Presets, take a look at the specialized configuration files provided by Babel instead.

There are two types of configuration files:

  1. Configuration of the project scope
  • babel.config.jsonFile. Available with extensions.json,.js,.cjs,.mjs.
  1. Relative file configuration
  • .babelrc.jsonFile. Available with extensions.json,.js,.cjs,.mjs. Or I could just call it theta.babelrc.
  • package.jsonFile. One of thekeybabelSettings.

Set both types of files in the project root directory. Babel automatically looks for it when it executes.

1. Configure the project scope

[email protected] starts with the concept of a root directory. The default is the current working directory. The directory where the Babel command is executed.

For project-wide configuration, the default search behavior is to look for babel.config.json directly in the directory where the translation command is currently executed.

├─ ├─ ├─ download.config.js ├─ ├─ download.config.js ├─ download.├ ─ download.config.js ├─ download.├ ─ download.├ ─ download.config.js ├─ download.download.js ├─ download.download.js ├─ download.download.js ├─ download.download.js ├─ download.download.js ├─ download.download.js ├─ download.download.js ├─ download.download.js └─ yarn.lockCopy the code

Assume that the directory structure in the project babel-config-demo looks like this.

So when the Babel command is executed in the babel-config-demo/ directory, it can be transcoded normally. Transcoding is not possible under babel-config-demo/ SRC.

You can also use the configFile option to specify the specific babel.config.json path. Note that this option is only allowed programmatically. Create a JS file, manually import @babel/core, call the API.

In addition, babel.config.json can transcode files in node_modules and symlinked packages. .babelrc.json does not.

From the above discussion, we briefly summarize the characteristics of the babel.config.json class file:

  • Must exist in the execution directory. The command must be found in the directory where the command is executedbabel.config.json.
  • If the project is special, use itconfigFileOption, explicitly specifiedbabel.config.jsonThe location of the.
  • babel.config.jsonCan also be thenode_modulessymlinked packagesTranscoding files inside.

2. Configure relative files

For the configuration of files, the default search behavior is to locate the translated target file according to the command, and search up the target file based on the location. Babelrc.json. There are two things to note during this search:

  • During this search, once encounteredpackage.json, the search stops.
  • If we find it,.babelrc.jsonthis.babelrc.jsonThe directory must be in the same level as the command. Otherwise,.babelrc.jsonIt will be ignored, the document will not be translated.

The sample a

├─ ├─ ├─ download.txt ├─ download.txt ├─ download.txt ├─ download.txt ├─ download.txt ├─ download.txt ├─ download.txt ├─ download.txt ├─ download.txt ├─ download.txtCopy the code

When running the YARN Compiler command in babelrc-demo/, SRC /main.js is located first. Then follow this file up to.babelrc. But since the SRC folder contains package.json, the search stops immediately and you look for.babelrc directly under SRC. As you can imagine, it doesn’t work.

Example 2

Babelrc - demo /. ├ ─ ─ package. The json ├ ─ ─ node_modules ├ ─ ─ the SRC | └ ─ ─ the babelrc │ ├ ─ ─ the main, js │ └ ─ ─ package. The json ├ ─ ─ the babelrc └ ─ ─ yarn. The lockCopy the code

This example has more.babelrc under SRC than the above example.

Similarly, when the YARN Compiler command is executed under babelrc-demo/, SRC /main.js is located first. Although.babelrc can be found under SRC at this point. Babelrc is not in the same directory as babelrc-demo/ SRC /, so the command fails to be executed.

conclusion

In most cases, there is not much difference between using project-scoped configurations and relative file configurations.

The main reason Babel divides configuration files into these two categories is to facilitate the management of mono Packages projects such as @babel. It can not only centrally manage the general Babel configuration (project-wide configuration), but also do individual configuration (relative file configuration) according to the actual situation of each package. When both configurations are found at the same time, the relative file configuration is merged with the project-scope configuration before it is applied to the subpackage.

4.plugins

As mentioned earlier, the core transformation of Babel is at @babel/core. @babel/core is just a converter, and Babel does nothing if plugins are not configured to declare the conversion rule.

Plug-ins fall into two categories: transformation plug-ins and syntax plug-ins.

The transformation plug-in

Configure in.babelrc:

{
  "plugins": ["@babel/plugin-transfrom-arrow-fuctions"]}Copy the code

Here are some common es6 plugins:

Arrow functions: @babel/plugin-transform-arrow-functions

class: @babel/plugin-transform-classes

for of: @babel/plugin-transform-for-of

Grammar plug-in

Configure in.babelrc:

{
  "parserOpts": {
    "plugins": ["jsx"."flow"]}}Copy the code

When some transformation plug-ins are used, the dependent syntax plug-ins are enabled by default.

So generally we don’t have to pay too much attention to the type and configuration of such plug-ins.

Plug-in order

  • The plug-inpresetsBefore the execution.
  • Plug-ins run from front to back.
  • presetsThe order is reversed, ie from back to front. This is for the sake ofbabelVersion iteration reasons to ensure downward compatibility.

The plug-in parameters

When setting parameters for plug-ins, you can write the plug-in items as arrays.

{
  "plugins": [["@babel/plugin-transform-arrow-functions", {
        "key": "value"}}]]Copy the code

5.presets

A default is a collection of plug-ins. This is for the convenience of developers in the actual application no longer need to manually configure various plug-ins.

The official preset

Babel officially offers some presets.

  • @babel/preset-env
  • @babel/preset-flow
  • @babel/preset-react
  • @bbael/preset-typescript

More the preset

The default usage configuration is roughly the same as for plug-ins.

The only thing to note is that the default execution order is the opposite of the plug-in.

@babel/preset-env

This preset can be called an environment preset.

When it comes to environments, there are two very important points: transcoding and polyfilling. It just so happens that @babel/preset-env helps us implement both of these things gracefully.

And because there are so many browser versions, we have to tell the preset when we use it what browser and version we are targeting. So you need to set browserslist.

For convenience, all preset-env in this chapter refer to @babel/preset-env.

browserslist

There are three configuration methods used in Babel with PRESET -env:

  1. .browserslistrc

Add the.browserslistrc file in the project root directory. Note that this file is a global configuration. For example, if the project has postCSS, it will also read that file.

> 1%
last 2 versions
not ie <= 8
Copy the code
  1. package.jsonSet in thebrowserslist.The role and priority of this configuration in the project scope are the same as those in the previous item.

Array form:

{
  "browserslist": [
    "1%" >."last 2 versions"."not ie <= 8"]}Copy the code

String format:

{
  "browserslist": "> 1%, last 2 versions, not ie <= 8"
}
Copy the code
  1. To the default@babel/preset-envSet up thetargetParameters.The priority is the highest of the three.
{
  "presets": [["@babel/preset-env", {
        "targets": [
          "1%" >."last 2 versions"."not ie <= 8"[}]]}Copy the code

options

Here are some common setting properties.

  1. targets

String | Array < string > | {[string] : string}, defaults to {}.

Used to set the target browser.

  1. modules

Systemjs umd “amd” | “” |” “|” commonjs “|” CJS “| |” auto “false, defaults to auto.

Used to set how modular the translated code should be. When set to false, ES Module is retained.

In a WebPack project, it is highly recommended to set it to false and hand the import over to WebPack.

Because Webpack can do tree shaking for ES Modules.

  1. useBuiltIns

“Usage” | | “entry” false. Default to false.

Used to configure PRESET -env how to handle polyfill.

  • "usage"Automatic import on demand.
  • "entry"Import from entry filepolyfill.preset-envWill import in fullpolyfill.
  • falseNo longer usepolyfill.

But preth-env doesn’t have polyfill built in, it’s just a collection of plug-ins. So we need to install @babel/ Polyfill before using this configuration property.

[email protected] has started deprecating @babel/polyfill. Core-js is recommended. When using core-js, you need to set it with the next property.

  1. core-js

2, 3 or { version: 2 | 3, proposals: boolean }, defaults to 2

Used to configure the version of Core-JS.

If the version is set to 2 or 3, you need to install core-js@2 or core-js@3.

  1. ignoreBrowserslistConfig

Boolean, defaults to false.

Configure whether to ignore the browserslist file and the Browserslist key in package.json.

6.polyfill

First of all, what is polyfill? Why do we need polyfill?

define

Polyfill means putty. It is responsible for smoothing out API differences in different environments.

Here’s a previously updated article about it.

Babel itself can only convert existing syntax, such as arrow functions to normal functions and classes to constructors.

However, it does not convert new syntax, such as Promise, includes, map, etc., which refer to new methods added to global or Object, Array, etc stereotypes.

@babel/polyfill

This library was originally a standalone library for Babel to provide Polyfill.

Starting at [email protected], it is recommended to introduce these libraries directly instead of @babel/ Polyfill.

import 'core-js/stable'
import 'regenerator-runtime/runtime'
Copy the code

@babel/polyfillThe use of

The original use

Import the full package directly into the import file:

import '@babel/polyfill'
Copy the code

In combination with@babel/preset-envuse

Babel does not recommend importing @babel/polyfill directly into the entry file. Because this approach introduces a full package, unwanted polyfills are also loaded, increasing the size of the package. Therefore, polyfill is often used in conjunction with PRESET -env.

  1. When settinguseBuiltInsfalseOr notuseBuiltInsOptions. Need to usewebpackentryProperty, set toAn array:
// webpack.config.js
module.exports = {
  entry: ['@babel/polyfill'.'./src/main.js']}Copy the code
  1. When settinguseBuiltIns'entry'According to the configuration itemcorejsThe specific configuration is also different.'entry'meaningThe entrance.babelWill be looking at the entrancepolyfillImport the full package.
// With corejs:2, the entry file main.js is introduced
import '@babel/polyfill'
// Install additional yarn add core-js@2

// When corejs:3, the entry file main.js is introduced
import "core-js/stable"
import "regenerator-runtime/runtime"
// Install additional yarn add core-js@3
Copy the code
  1. When settinguseBuiltIns'usage'.polyfillautomaticbeAccording to the need to introduceOnly the ones used will be loadedpolyfill, but note that installation is still required@babel/polyfillThe package. It just doesn’t need to be configured manually.

Because Babel is moving away from polyfill, you may encounter an error when setting useBuiltIns:

WARNING: We noticed you're using the `useBuiltIns` option without declaring a core-js version. Currently, we assume version 2.x when no version is passed. Since this default version will likely change in future versions of Babel, we recommend explicitly setting the core-js version you are using via the `corejs` option.

You should also be sure that the version you pass to the `corejs` option matches the version specified in your `package.json`'s `dependencies` section. If it doesn't, you need to run one of the following commands:

  npm install --save core-js@2    npm install --save core-js@3
  yarn add core-js@2              yarn add core-js@3
Copy the code

Obviously, Babel recommends using Core-JS. So the solution to this problem is to install Core-js and state its version of use in PRESET -env.

@babel/polyfillThe abandoned

@babel/ Polyfill was scrapped for two reasons:

  1. Each translated file may generate a large number of duplicateshelperUtility functions, code redundancy, package size increase.
  2. @babel-polyfillModify global variables. Adverse to the use of third-party public libraries.

Let’s look at preset-env and @babel/polyfill translated into code. Excerpt from the core:

"use strict";
require("@babel/polyfill");
var _this = void 0;

// There are a lot of helper functions at the top of the file
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; }

function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { Promise.resolve(value).then(_next, _throw); }}function _asyncToGenerator(fn) { return function () { var self = this, args = arguments; return new Promise(function (resolve, reject) { var gen = fn.apply(self, args); function _next(value) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value); } function _throw(err) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err); } _next(undefined); }); }; }

function _classCallCheck(instance, Constructor) { if(! (instanceinstanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); }}function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); }}function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }

// async (async) ¶ You can see that the variable regeneratorRuntime is created out of thin air.
function _fn() {
  _fn = _asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee() {
    var result;
    return regeneratorRuntime.wrap(function _callee$(_context) {
      while (1) {
        switch (_context.prev = _context.next) {
          case 0:
            _context.prev = 0;
            _context.next = 3;
            return promise;

          case 3:
            result = _context.sent;
            console.log(result);
            _context.next = 10;
            break;

          case 7:
            _context.prev = 7;
            _context.t0 = _context["catch"] (0);
            console.warn('error', _context.t0);

          case 10:
            console.log('--- after promise ---');

          case 11:
          case "end":
            return _context.stop();
        }
      }
    }, _callee, nullThe [[0.7]]);
  }));
  return _fn.apply(this.arguments);
}
Copy the code

From the above code, you can see two parts of the problem:

  1. _interopRequireDefault, asyncGeneratorStep, _asyncToGenerator, _classCallCheck, _defineProperties, and _createClass are preset-env Generated helper utility class functions. If you have multiple Babel translated files, these functions will exist in those files.

  2. New global variable regeneratorRuntime. The introduction of @babel/polyfill exposes this global variable to keep the code running. Otherwise, an error is reported when the code is run. RegeneratorRuntime is not defined.

These two parts of the problem are resolved by @babel/plugin-transfrom-runtime. It imports both the helper tool functions and regeneratorRuntime from the @babel/ Runtime library.

7.transform runtime

At the end of the previous chapter, we briefly introduced @babel/ plugin-transform-Runtime.

It is mainly used to solve problems that arise when @babel/ Polyfill is used in combination with preset-env.

We’ll look at it in detail in this chapter.

The installation

@babel/ plugin-transform-Runtime is a plugin for Babel. It is usually used in conjunction with @babel/ Runtime.

yarn add @babel/plugin-transform-runtime -D

#This library may not need to be manually installed. Babel may install the Runtime library automatically when installing the above plug-ins. In addition, because it is a production dependency, it is not added here'-D'
yarn add @babel/runtime
Copy the code

Use reasons

@babel/plugin-transform-runtime replaces @babel/polyfill. It has two main advantages:

  1. In a single translated code file, there are manyhelperUtility functions, if multiple files are translated in a project, can be expected to have a lot of duplicationhelperTool function to increase the size of the project package.

@babel/ plugin-transform-Runtime will import all helper functions from the @babel/ Runtime library.

  1. @babel/polyfillContaminates the global scope and is not conducive to use in third-party libraries.

Babel /plugin-transform-runtime creates a sandbox environment to ensure that the code environment is not polluted.

Method of use

Since @babel/ plugin-transform-Runtime is a plug-in, it can be configured as a plug-in. Take the babelrc file as an example:

{
  "plugins": [["@babel/plugin-transform-runtime", {
        "corejs": 3."helpers": true."regenerator": true."useESModules": false,}]],"presets": []}Copy the code

Configuration options

1.corejs

2, 3 or { version: 2 | 3, proposals: boolean }, defaults to 2

This is used to declare a core-js version of the @babel/plugin-transform-runtime translated code.

This option is equivalent to replacing Polyfill. You do not need to use polyfill after setting this. There will be @babel/ Runtime-corejs.

core-js@2 supports only global variables (such as Promise) and static properties (such as array.from).

core-js@3 also supports instance attributes (such as [].includes).

So we typically set this to corejs: 3.

2.helpers

Boolean, defaults to true.

Set whether to convert _asyncToGenerator, _classCallCheck, and _createClass helpers into modular imports.

// Polyfill declares a bunch of functions in the header of the file

// Set corejs to 3 under transform-runtime
import _asyncToGenerator from "@babel/runtime-corejs3/helpers/esm/asyncToGenerator";
import _setTimeout from "@babel/runtime-corejs3/core-js-stable/set-timeout";
import _createClass from "@babel/runtime-corejs3/helpers/esm/createClass";
Copy the code

3.regenerator

Boolean, defaults to true.

Sets whether _regeneratorRuntime is converted to a modular import.

// Polyfill is a global variable

// Set corejs to 3 under transform-runtime
import _regeneratorRuntime from "@babel/runtime-corejs3/regenerator"
Copy the code

@babel/runtime

If corejs is not set for @babel/ plugin-transform-Runtime, helpers and Regenerator are imported from @babel/ Runtime by default.

Note: Without corejs set, the translated code is similar to corejs: 2. Instance attributes are not supported.

"use strict";

var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");

var _regenerator = _interopRequireDefault(require("@babel/runtime/regenerator"));

var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator"));

var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck"));

var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/createClass"));
Copy the code

@babel/runtime-corejs2

"use strict";

var _interopRequireDefault = require("@babel/runtime-corejs2/helpers/interopRequireDefault");

var _regenerator = _interopRequireDefault(require("@babel/runtime-corejs2/regenerator"));

var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime-corejs2/helpers/asyncToGenerator"));

var _promise = _interopRequireDefault(require("@babel/runtime-corejs2/core-js/promise"));

var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime-corejs2/helpers/classCallCheck"));

var _createClass2 = _interopRequireDefault(require("@babel/runtime-corejs2/helpers/createClass"));
Copy the code

@babel/runtime-corejs3

import _regeneratorRuntime from "@babel/runtime-corejs3/regenerator";

import _includesInstanceProperty from "@babel/runtime-corejs3/core-js-stable/instance/includes";

import _asyncToGenerator from "@babel/runtime-corejs3/helpers/esm/asyncToGenerator";

import _setTimeout from "@babel/runtime-corejs3/core-js-stable/set-timeout";

import _Promise from "@babel/runtime-corejs3/core-js-stable/promise";

import _classCallCheck from "@babel/runtime-corejs3/helpers/esm/classCallCheck";

import _createClass from "@babel/runtime-corejs3/helpers/esm/createClass";

Copy the code

8. To summarize

After the previous introduction, let’s summarize the configuration methods for [email protected] version and above.

In terms of browser compatibility, there are usually two types: @babel/polyfill and @babel/ plugin-transform-Runtime.

For preset, @babel/preset-env is usually used. Based on the polyfill and transform-Runtime used above, preset-env is configured differently.

The configuration is as follows:

polyfill

// babel.config.js
module.exports = {
 presets: [["@babel/preset-env", {
    // By default, the ES Module is used for tree shaking in Webpack
    modules: false.// Optional value Usage Entry false(not recommended Entry or false)
    useBuiltIns: "usage".// Corejs version (required if useBuiltIns is set)
    corejs: 3.// The target browser preset-env must be set, or a.browerslistrc file is used instead
    targets: [
      "1%" >."last 2 versions"."not ie <= 8"]}}]]Copy the code

If the useBuiltIns set above is Entry, you need to manually introduce Polyfill in the entry file.

In addition, the way polyfill is introduced varies depending on the version of corejs set. As follows:

// corejs: 2
import '@babel/polyfill'

// corejs: 3
import "core-js/stable"
import "regenerator-runtime/runtime"
Copy the code

transform-runtime

Of course, we know that Babel no longer recommends importing polyfill directly, instead using the @babel/ plugin-transform-Runtime plugin.

// babel.config.js
module.exports = {
  presets: [["@babel/preset-env", {
      / / use EsModule
      modules: false.targets: [
        "1%" >."last 2 versions"."not ie <= 8"]}]]plugins: [["@babel/plugin-transform-runtime", {
      // The useBuiltIns property is set by default
      // Corejs setting 3 is recommended, as this version supports instance attributes
      corejs: 3}}]]Copy the code

Also, note that depending on the corejs version, the corresponding run-time Corejs needs to be installed.

# corejs: 2
yarn add @babel/runtime-corejs2

# corejs: 3
yarn add @babel/runtime-corejs3
Copy the code