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:
- Syntax conversion. For instance, will
es6
The arrow function is converted to a normal function compatible with lower versions of browsers. - through
Polyfill
Way to add missing features to the target environment (through@babel/polyfill
Modules). - Source code conversion. Such as the conversion
typescript
,jsx
And 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.
- perform
yarn init -y
. - create
src
Directory. - in
src
Create 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/cli
Official scaffolding.@babel/core
, core conversion module.@babel/plugins
or@babel/presets
Specific conversion rules.@babel/polyfill
Putty is required for earlier versions of browsers. However,babel
There have been new uses to compensate@babel/polyfill
Existing 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:
- Configuration of the project scope
babel.config.json
File. Available with extensions.json
,.js
,.cjs
,.mjs
.
- Relative file configuration
.babelrc.json
File. Available with extensions.json
,.js
,.cjs
,.mjs
. Or I could just call it theta.babelrc
.package.json
File. One of thekey
为babel
Settings.
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 executed
babel.config.json
. - If the project is special, use it
configFile
Option, explicitly specifiedbabel.config.json
The location of the. babel.config.json
Can also be thenode_modules
和symlinked packages
Transcoding 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 encountered
package.json
, the search stops. - If we find it,
.babelrc.json
this.babelrc.json
The directory must be in the same level as the command. Otherwise,.babelrc.json
It 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-in
presets
Before the execution. - Plug-ins run from front to back.
presets
The order is reversed, ie from back to front. This is for the sake ofbabel
Version 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:
.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
package.json
Set 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
- To the default
@babel/preset-env
Set up thetarget
Parameters.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.
targets
String | Array < string > | {[string] : string}, defaults to {}.
Used to set the target browser.
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.
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-env
Will import in fullpolyfill
.false
No 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.
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.
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/polyfill
The 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-env
use
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.
- When setting
useBuiltIns
为false
Or notuseBuiltIns
Options. Need to usewebpack
的entry
Property, set toAn array:
// webpack.config.js
module.exports = {
entry: ['@babel/polyfill'.'./src/main.js']}Copy the code
- When setting
useBuiltIns
为'entry'
According to the configuration itemcorejs
The specific configuration is also different.'entry'
meaningThe entrance.babel
Will be looking at the entrancepolyfill
Import 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
- When setting
useBuiltIns
为'usage'
.polyfill
会automaticbeAccording to the need to introduceOnly the ones used will be loadedpolyfill
, but note that installation is still required@babel/polyfill
The 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/polyfill
The abandoned
@babel/ Polyfill was scrapped for two reasons:
- Each translated file may generate a large number of duplicates
helper
Utility functions, code redundancy, package size increase. @babel-polyfill
Modify 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:
-
_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.
-
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:
- In a single translated code file, there are many
helper
Utility functions, if multiple files are translated in a project, can be expected to have a lot of duplicationhelper
Tool function to increase the size of the project package.
@babel/ plugin-transform-Runtime will import all helper functions from the @babel/ Runtime library.
@babel/polyfill
Contaminates 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