@babel/core
核心功能
@babel/cli
命令行工具
@babel/preset-env
转换语法
@babel/polyfill
补充 API、提供 regeneratorRuntime 函数
core-js
补充 API
regenerator-runtime
提供 regeneratorRuntime 函数
@babel/plugin-transform-runtime
替换内联帮助函数、替换全局 API、提供 regeneratorRuntime 函数
本章介绍除了 @babel/plugin-transform-runtime
包之外的其他包的使用。
是否受到 browserslist 影响
-
@babel/preset-env
负责转换语法,@babel/polyfill
负责补充 API -
@babel/preset-env
转换语法会受到 browserslist 目标环境的影响 -
@babel/polyfill
补充 API 默认不受 browserslist 目标环境的影响 - 配置
@babel/preset-env
的 useBuiltIns 选项为 'entry' 或 'usage' 时候,补充 API 会受到 browserslist 目标环境的影响。
@babel/core
@babel/core
是我们使用 Babel 进行转码的核心 NPM 包,我们使用的 babel-cli
、babel-node
都依赖这个包。无论我们是通过命令行转码,还是通过 Webpack 进行转码,底层都是通过 Node 来调用 @babel/core
相关功能 API 来进行的。因此我们在前端开发的时候,只要用到 Babel 转码,都需要安装这个包。
在我们的工程目录里,执行下面的命令,安装 @babel/core
。
npm i -D @babel/core
以下例子通过 Node 调用 @babel/core
的 API 来进行转码
var babelCore = require('@babel/core');
var es6Code = 'var fn = (num) => num + 2';
var options = {
presets: ['@babel/preset-env']
};
var result = babelCore.transform(es6Code, options);
console.log(result.code);
@babel/cli
@babel/cli
是一个 NPM 包,安装了它之后就可以在命令行使用 Babel 进行转码。安装 @babel/cli
之前必须先安装 @babel/core
。
全局安装
npm i @babel/core @babel/cli -g
本地安装(推荐)
npm i -D @babel/core @babel/cli
使用
# 转码并输出到标准输出
npx babel a.js
# 转码并生成文件
npx babel a.js -o b.js
# 对整个目录进行转码
npx babel input -d output
@babel/polyfill
@babel/polyfill
是一个 NPM 包,通过在前端工程的入口文件引入 @babel/polyfill
包,可以在全局范围补齐新的 API。@babel/polyfill
其实就是两个 npm 包的集合:core-js
与 regenerator-runtime
,从 babel 7.4 开始,官方推荐单独安装 core-js
和 regenerator-runtime
来代替 @babel/polyfill
。
- 安装
@babel/polyfill
包的时候,会自动安装core-js
与regenerator-runtime
,其中core-js
的版本为 2 -
@babel/polyfill
会自动调用core-js
来添加 API。 -
@babel/polyfill
会自动调用regenerator-runtime
来定义 regeneratorRuntime 函数。 - 在前端工程的入口文件的开头引入
@babel/polyfill
。 - 只能引入一次
@babel/polyfill
,多次引用会报错。 - 通过 webpack 构建之后,
import '@babel/polyfill'
默认会将所有 ES6 API 添加到代码中,不会考虑 browserslist 当中的目标环境。 -
@babel/polyfill
会在构建后的代码中添加全局对象 API、全局对象的属性 API、实例的原型属性 API。 -
@babel/polyfill
会在构建后的代码中添加 regeneratorRuntime 函数。 - 通过修改
@babel/preset-env
的 useBuiltIns 选项,可以影响@babel/polyfill
的使用方式。
npm i @babel/polyfill
/* 入口文件 */
import '@babel/polyfill'
let todos = new Set(['vue', 'react']);
let promise = Promise.resolve('ok');
function* gen () {
yield* todos;
}
for (let todo of gen()) {
console.log(todo);
}
core-js
- 安装
core-js
和regenerator-runtime
的时候,不需要安装@babel/polyfill
- 安装
core-js
可以指定版本,默认最新的版本,2022 年 4 月最新的版本为 3。 - 安装
@babel/polyfill
时候自动安装的core-js
版本为 2。 - 新版本的
core-js@3
比core-js@2
多了许多新的 API,例如Array.prototype.includes
。 - 在前端工程的入口文件的开头
import 'core-js/stable'
来导入 API,只能导入一次,导入多次会报错。 - 如果使用
import 'core-js/stable'
导入 API,需要安装core-js@3
版本,因为core-js@2
版本没有core-js/stable
。 - 通过 webpack 构建之后,
import 'core-js/stable'
默认会将所有的 ES6 API 添加到代码中,不会考虑 browserslist 当中的目标环境。 -
core-js
会在构建后的代码中添加全局对象 API、全局对象的属性 API、实例的原型属性 API。
npm i core-js
配置文件:
const presets = ['@babel/env']
const plugins = []
module.exports = {
presets,
plugins
}
转换之前:
import "core-js/stable";
var promise = Promise.resolve();
经过 Babel 转换之后:
"use strict";
// 下面的一行代码经过 Webpack 打包之后,会将 core-js/stable 包中的所有 API 引入到最终的文件中。
require("core-js/stable");
var promise = Promise.resolve();
经过 Webpack 打包之后,core-js/stable
包中的所有 API 都会被引入到最终的文件中。
regenerator-runtime
- 如果代码中有 Generator/async 函数语法,则在语法转换的时候,
@babel/preset-env
会将 Generator/async 函数转换为调用 regeneratorRuntime 函数。 -
regenerator-runtime
包提供了 regeneratorRuntime 函数的定义,regenerator-runtime
包可以单独安装,也可以在安装@babel/polyfill
的时候自动安装。 - 通过
import regenerator-runtime
可以获得 regeneratorRuntime 函数的定义。 - 通过
import @babel/polyfill
也可以获得 regeneratorRuntime 函数的定义。 - 一般在前端工程的入口文件
import regenerator-runtime
或者import regenerator-runtime/runtime
来引入 regeneratorRuntime 函数的定义,只能引入一次,引入多次会报错。
npm i regenerator-runtime
配置文件:
const presets = ['@babel/env']
const plugins = []
module.exports = {
presets,
plugins
}
转换之前:
import "regenerator-runtime/runtime";
function* gen () {
yield 100;
yield 200;
}
经过 Babel 转换之后:
"use strict";
// 下面的一行代码,经过 Webpack 打包之后,会引入 regenerator-runtime 包中的 regeneratorRuntime 函数定义。
require("regenerator-runtime");
var _marked = /*#__PURE__*/regeneratorRuntime.mark(gen);
function gen() {
return regeneratorRuntime.wrap(function gen$(_context) {
while (1) {
switch (_context.prev = _context.next) {
case 0:
_context.next = 2;
return 100;
case 2:
_context.next = 4;
return 200;
case 4:
case "end":
return _context.stop();
}
}
}, _marked);
}
经过 Webpack 打包之后,会将 regenerator-runtime
包中的 regeneratorRuntime 函数引入到最终的文件中。
@babel/preset-env
@babel/preset-env
预设集合了自 ES2015 以来所有最新的语法插件,用来对标准的 ES6 语法转换。它只转换 ES6 语法,不会添加 ES6 新增的 API。@babel/env
是 @babel/preset-env
的简写。
通过配置文件,可以配置 @babel/preset-env
预设需要的参数,常用的参数:
- targets
- useBuiltIns
- corejs
- modules
targets
该参数可以取值为字符串、字符串数组或对象。如果不设置,默认值为空对象 {}
。
与 browserslist 功能一样,指定转码的目标环境。@babel/preset-env
转换语法的时候,将目标环境不支持的 ES6 语法进行转码,目标环境支持的 ES6 语法不转码。可以通过 browserslist 指定目标环境,也可以通过 targets 属性指定目标环境。如果没有指定目标环境,@babel/preset-env
默认会将所有的 ES6 语法进行编码。
- 如果指定了 targets 选项,就不使用 browserslist 的配置。
- 如果没有指定 targets 选项,则使用 browserslist 的配置。
- 推荐使用 browserslist 的配置,不推荐配置 targets 属性。
const presets = [
[
'@babel/preset-env',
{
targets: [
'> 1%',
'last 2 versions',
'not ie <= 8'
]
}
]
]
const plugins = []
module.exports = {
presets,
plugins
}
useBuiltIns
@babel/preset-env
的 useBuiltIns 参数主要和 @babel/polyfill
的行为有关,该参数值可以是 "usage" 、 "entry" 或 false。如果不设置,默认值为 false。
useBuiltIns: false
useBuiltIns 没有配置或取值为 false 时候,在代码中 import '@babel/polyfill'
,打包之后会将所有的 ES6 API 都导入到代码中。不管是否通过 browserslist 或者 targets 属性设置了目标环境,import '@babel/polyfill'
都会将所有的 ES6 API 都导入到代码中,哪怕目标环境支持的 API 也会导入进来。
useBuiltIns: false
代表 babel 不会对源码中的 import '@babel/polyfill'
做任何转换,经过 babel 转码之后,import '@babel/polyfill'
仍然存在与源码中。webpack 打包的时候,会引入 @babel/polyfill
包的所有模块,也就是引入全部的 ES6 API。
/* babel.config.js */
const presets = [
[
'@babel/env',
{
targets: ['chrome 60'],
useBuiltIns: false
}
]
]
const plugins = []
module.exports = {
presets,
plugins
}
/* entry.js */
// 导入所有 API
import '@babel/polyfill';
var promise = Promise.resolve('ok');
console.log(promise);
useBuiltIns: 'entry'
useBuiltIns 取值为 'entry' 的时候,在代码中 import '@babel/polyfill'
,会根据 browserslist 或者 target 属性配置的目标环境,找出目标环境需要的 ES6 API 进行部分导入。
useBuiltIns 值为 'entry' 的时候,最好同时设置 corejs 属性。
userBuiltIns: 'entry'
在 babel 转码的时候,会将 import '@babel/polyfill'
语句转换为一堆 import
语句,来引入全部的 ES6 API。如果指定了 .browserslistrc
文件,则只 import
浏览器不支持的 ES6 API。
/* babel.config.js */
const presets = [
[
'@babel/env',
{
targets: ['chrome 60'],
useBuiltIns: 'entry',
corejs: 2
}
]
]
const plugins = []
module.exports = {
presets,
plugins
}
/* entry.js */
// 导入 chrome 60 浏览器不支持的所有 API
import '@babel/polyfill';
var promise = Promise.resolve('ok');
console.log(promise);
useBuiltIns: 'usage'
useBuiltIns 取值为 'usage' 时候,不需要在文件中 import '@babel/polyfill'
或者 import 'core-js/stable'
import 'regenerator-runtime/runtime'
,转码时候会根据 browserslist 或者 targets 属性设置的目标环境,自动导入当前代码中使用到的且目标环境不支持的 API。
useBuiltIns 值为 'usage' 的时候,最好同时设置 corejs 属性。
/* babel.config.js */
const presets = [
[
'@babel/env',
{
targets: ['chrome 60'],
useBuiltIns: 'usage',
corejs: 2
}
]
]
const plugins = []
module.exports = {
presets,
plugins
}
/* entry.js */
// 自动导入当前代码中使用到的且 chrome 60 浏览器不支持的 API
var promise = Promise.resolve('ok');
console.log(promise);
useBuiltIns: 'entry' 与 useBuiltIns: 'usage' 对比
相同点:
- 都需要参考 browserslist 或者 targets 属性设置的目标环境。
- 都需要同时设置 corejs 属性。
不同点:
- 'entry' 需要我们在项目入口处手动引入 polyfill,而 'usage' 不需要。
- 'entry' 引入目标环境不支持的所有 API,而 'usage' 按需引入目标环境不支持,且当前代码中使用到的 API 。
corejs
该参数项的取值可以是 2 或 3,没有设置的时候取默认值为 2,指定转码的时候使用的 core-js
的版本。
这个参数只有 useBuiltIns 设置为 'usage' 或 'entry' 时,才会生效。
安装 @babel/polyfill
包的时候,会自动安装 core-js@2
版本,因此如果代码中通过 import '@babel/polyfill'
导入 API,则需要将 corejs 属性值设置为 2。
如果代码中通过 import 'core-js/stable'
和 import 'regenerator-runtime/runtime'
导入 API,那么需要单独安装 core-js@3
版本,因为 core-js@2
版本没有 core-js/stable
。这时候需要将 corejs 属性值设置为 3。
只要安装了 core-js@3
版本,corejs 属性就必须设置为 3,否则转码时候报错。由于 @babel/polyfill
内部是通过调用 core-js@2
来引入 API 的,所以这时候就不能使用 @babel/polyfill
了,只能使用 core-js/stable
。如果此时还想要使用 @babel/polyfill
,那么你需要再单独安装一个 core-js@2
,并且将 corejs 属性设置为 2。
推荐要么使用 @babel/polyfill
并且将 corejs 设置为 2,要么使用 core-js/stable
并且将 corejs 设置为 3。@babel/polyfill
和 core-js@3
这两个包最好不要同时安装。
modules
这个参数的取值可以是"amd"、"umd" 、 "systemjs" 、 "commonjs" 、"cjs" 、"auto" 、false。在不设置的时候,取默认值"auto"。
- 设置该参数用来将代码中的 ES6 的模块转换成其他的模块,常用 'auto' 或 false。
- 在该参数值是 'auto' 'commonjs' 或不设置的时候,会将 ES6 的模块转化为 CommonJS 的模块。
- 在该参数值是 false 的时候,保留 ES6 模块,不会转换 ES6 模块为其他模块。
- 该参数只影响通过 Babel 转码后的代码,不影响通过 Webpack 打包最终生成的代码,因为不管使用 ES6 模块还是使用 CommonJS 模块,Webpack 的依赖图都一样,最终生成的代码都一样,都是通过
__webpack_require__()
这个内部的方法来引入模块。 - 推荐将 modules 值设置为 false,使用 ES6 模块,这样在用 Webpack 打包的时候可以做静态分析。