跳至主要内容

升级到 Babel 7

升级到 Babel 7 时,请参阅本文档。有关 API/集成更改,请查看此处

由于并非每个重大更改都会影响每个项目,因此我们根据升级时更改导致测试中断的可能性对各部分进行了排序。

所有 Babel

已放弃对 Node.js 0.10、0.12、4 和 5 的支持 #5025#5041#7755#5186

我们强烈建议您使用较新版本的 Node.js (LTS v8),因为以前的版本不再维护。有关更多信息,请参阅 nodejs/LTS

这仅仅意味着 Babel 本身 无法在旧版本的 Node 上运行。它仍然可以输出可在旧 Node 版本上运行的代码。

配置查找更改

有关更多信息,请阅读我们的6.x 与 7.x 比较

Babel 之前在处理 node_modules、符号链接和多包存储库时遇到过问题。我们为此做了一些更改:Babel 将在 package.json 边界处停止查找,而不是向上查找链。对于多包存储库,我们添加了一个新的 babel.config.js 文件,用于集中管理所有包的配置(或者,您可以为每个包创建一个配置)。在 7.1 中,我们引入了一个 rootMode 选项,以便在必要时进行进一步查找。

年度预设弃用

“env”预设已经推出一年多了,它完全取代了我们之前提供和建议的一些预设。

  • babel-preset-es2015
  • babel-preset-es2016
  • babel-preset-es2017
  • babel-preset-latest
  • 以上各项的组合 ^

这些预设应该用“env”预设代替。

阶段预设弃用

我们正在删除阶段预设,转而支持显式提案使用。可以查看 stage-0 自述文件 了解更多迁移步骤。

要自动执行此操作,您可以运行 npx babel-upgrade(PR 已添加 此处)。

删除 @babel/polyfill 中的提案 polyfill

基于类似的想法,我们从 @babel/polyfill 中删除了 polyfill 提案。

现在,@babel/polyfill 基本上只是 core-js v2 的别名。来源

之前它只是 2 个导入

JavaScript
import "core-js/shim"; // included < Stage 4 proposals
import "regenerator-runtime/runtime";

如果要使用提案,则需要单独导入它们。您应该直接从 core-js 包或 npm 上的其他包导入它们。

例如:

JavaScript
// for core-js v2:
import "core-js/fn/array/flat-map";

// for core-js v3:
import "core-js/features/array/flat-map";

以下是 core-js v2 中阶段 < 3 提案 polyfill 的列表。

详细信息
JavaScript
// core-js v2

// Stage 3
import "core-js/fn/string/trim-left";
import "core-js/fn/string/trim-right";
import "core-js/fn/string/match-all";
import "core-js/fn/array/flat-map";
import "core-js/fn/array/flatten"; // RENAMED
import "core-js/fn/global";

// Stage 1
import "core-js/fn/symbol/observable";
import "core-js/fn/promise/try";
import "core-js/fn/observable";

// Stage 1 Math Extensions
import "core-js/fn/math/clamp";
import "core-js/fn/math/deg-per-rad";
import "core-js/fn/math/degrees";
import "core-js/fn/math/fscale";
import "core-js/fn/math/iaddh";
import "core-js/fn/math/isubh";
import "core-js/fn/math/imulh";
import "core-js/fn/math/rad-per-deg";
import "core-js/fn/math/radians";
import "core-js/fn/math/scale";
import "core-js/fn/math/umulh";
import "core-js/fn/math/signbit";

// Stage 1 "of and from on collection constructors"
import "core-js/fn/map/of";
import "core-js/fn/set/of";
import "core-js/fn/weak-map/of";
import "core-js/fn/weak-set/of";
import "core-js/fn/map/from";
import "core-js/fn/set/from";
import "core-js/fn/weak-map/from";
import "core-js/fn/weak-set/from";

// Stage 0
import "core-js/fn/string/at";

// Nonstandard
import "core-js/fn/object/define-getter";
import "core-js/fn/object/define-setter";
import "core-js/fn/object/lookup-getter";
import "core-js/fn/object/lookup-setter";
// import "core-js/fn/map/to-json"; // Not available standalone
// import "core-js/fn/set/to-json"; // Not available standalone

import "core-js/fn/system/global";
import "core-js/fn/error/is-error";
import "core-js/fn/asap";

// Decorator metadata? Not sure of stage/proposal
import "core-js/fn/reflect/define-metadata";
import "core-js/fn/reflect/delete-metadata";
import "core-js/fn/reflect/get-metadata";
import "core-js/fn/reflect/get-metadata-keys";
import "core-js/fn/reflect/get-own-metadata";
import "core-js/fn/reflect/get-own-metadata-keys";
import "core-js/fn/reflect/has-metadata";
import "core-js/fn/reflect/has-own-metadata";
import "core-js/fn/reflect/metadata";

版本控制/依赖项

大多数插件/顶级包现在对 @babel/core 具有 peerDependency

包重命名

  • babylon 现在是 @babel/parser

您仍然可以在配置中使用包名称的简写版本(删除 preset-plugin-),但我选择使用完整的包名称以保持清晰度(也许我们应该删除它,因为它不会节省那么多输入)。

{
- "presets": ["@babel/preset-react"],
+ "presets": ["@babel/react"], // this is equivalent
- "plugins": ["@babel/transform-runtime"],
+ "plugins": ["@babel/plugin-transform-runtime"], // same
}

作用域包

最重要的变化是最终将所有包切换为作用域包多包存储库中的文件夹名称未更改,但其 package.json 中的名称已更改)。

这意味着将不再出现意外/故意名称抢注的问题,与社区插件明确分离,并且命名约定更简单。

您的依赖项需要修改如下

babel-cli -> @babel/cli。对于我们来说,我们基本上是从将 babel- 替换为 @babel/ 开始的。

在配置中使用

您仍然可以使用简写方式指定预设或插件。但是,由于切换到作用域包,您仍然必须指定 @babel/,就像您有自己的预设要添加到配置中一样。

babel.config.js
module.exports = {
presets: ["@babel/env"], // "@babel/preset-env"
plugins: ["@babel/transform-arrow-functions"], // same as "@babel/plugin-transform-arrow-functions"
};

切换到 -proposal- 以获取 TC39 提案

这意味着任何不在年度版本(ES2015、ES2016 等)中的插件都应重命名为 -proposal。这是为了让我们能够更好地表明提案尚未正式纳入 JavaScript。

示例

  • @babel/plugin-transform-function-bind 现在是 @babel/plugin-proposal-function-bind(阶段 0)
  • @babel/plugin-transform-class-properties 现在是 @babel/plugin-proposal-class-properties(阶段 3)

这也意味着,当提案进入阶段 4 时,我们应该重命名该包。

从包名称中删除年份

有些插件的名称中包含 -es3--es2015-,但这些是不必要的。

@babel/plugin-transform-es2015-classes 变成了 @babel/plugin-transform-classes

CommonJS 中的 "use strict"this

Babel 6 对 ES6 模块的转换不加选择地运行在它被告知要处理的任何文件上,从不考虑该文件实际上是否包含 ES6 导入/导出。这导致将文件范围内的 this 引用重写为 undefined,并在 Babel 处理的所有 CommonJS 模块的顶部插入 "use strict"

JavaScript
// input.js
this;
JavaScript
// output.js v6
"use strict"; // assumed strict modules
undefined; // changed this to undefined
JavaScript
// output.js v7
this;

此行为已在 Babel 7 中受到限制,因此对于 transform-es2015-modules-commonjs 转换,仅当文件包含 ES6 导入或导出时,才会更改该文件。(编者注:如果我们加入 https://github.com/babel/babel/issues/6242,这可能会再次发生变化,因此我们希望在发布之前重新审视这一点)。

JavaScript
// input2.js
import "a";
JavaScript
// output.js v6 and v7
"use strict";
require("a");

如果您依赖 Babel 自动将 "use strict" 注入到所有 CommonJS 模块中,则需要在 Babel 配置中显式使用 transform-strict-mode 插件。

React 和 Flow 预设的分离

babel-preset-react 始终包含 flow 插件。这导致许多用户由于拼写错误而意外使用 flow 语法,或者在没有使用 flow 本身进行类型检查的情况下添加它,从而导致错误。

当我们决定支持 TypeScript 时,这个问题更加严重。如果您想同时使用 React 和 TypeScript 预设,我们将不得不找到一种方法,通过文件类型或指令自动打开/关闭语法。最后,完全分离预设更容易。

预设使 Babel 能够解析 Flow / TypeScript(以及其他方言/语言)提供的类型,然后在编译为 JavaScript 时将它们剥离。

{
- "presets": ["@babel/preset-react"]
+ "presets": ["@babel/preset-react", "@babel/preset-flow"] // parse & remove flow types
+ "presets": ["@babel/preset-react", "@babel/preset-typescript"] // parse & remove typescript types
}

选项解析

Babel 的配置选项比 Babel 6 更严格。在 Babel 6 中,预设的逗号分隔列表(例如 "presets": 'es2015, es2016')在技术上是可行的,但现在会失败,需要更改为数组 #5463

请注意,这不适用于 CLI,在 CLI 中,--presets es2015,es2016 肯定仍然有效。

{
- "presets": "@babel/preset-env, @babel/preset-react"
+ "presets": ["@babel/preset-env", "@babel/preset-react"]
}

插件/预设导出

为了保持一致性,所有插件/预设现在都应该导出一个函数而不是一个对象(通过 babel/babel#6494)。这将有助于我们进行缓存。

解析基于字符串的配置值

在 Babel 6 中,传递给 Babel 的值(不是来自配置文件)是相对于正在编译的文件解析的,这导致了很多混乱。

在 Babel 7 中,值始终相对于加载它们的配置文件或相对于工作目录进行解析。

对于 presetsplugins 值,此更改意味着 CLI 在以下情况下将表现良好

Shell
babel --presets @babel/preset-env ../file.js

假设您的 node_modules 文件夹位于 . 中,则在 Babel 6 中,这将失败,因为找不到预设。

此更改还会影响 onlyignore,接下来将对此进行详细说明。

基于路径的 onlyignore 模式

在 Babel 6 中,onlyignore 被视为一般的匹配字符串,而不是文件路径 glob。这意味着例如 *.foo.js 将匹配 ./**/*.foo.js,这对大多数用户来说是混乱和令人惊讶的。

在 Babel 7 中,这些现在被视为基于路径的 glob 模式,可以是相对路径或绝对路径。这意味着,如果您正在使用这些模式,您可能至少需要在它们前面添加一个 **/ 前缀,以确保您的模式能够深入到目录中进行匹配。

onlyignore 模式确实仍然适用于目录,因此您也可以使用 only: './tests' 来仅编译 tests 目录中的文件,而无需使用 **/*.js 来匹配所有嵌套文件。

Babel 的 CLI 命令

babel 命令的 --copy-files 参数,它告诉 Babel 复制目录中 Babel 不知道如何处理的所有文件,现在也将复制未通过 only/ignore 检查的文件,而之前它会静默地跳过所有被忽略的文件。

@babel/node

Babel 6 中的 babel-node 命令是 babel-cli 包的一部分。在 Babel 7 中,此命令已被拆分为它自己的 @babel/node 包,因此如果您正在使用该命令,您需要添加这个新的依赖项。

@babel/runtime, @babel/plugin-transform-runtime

我们已将 Babel 的辅助函数与其在运行时的“polyfilling”行为分离。更多细节请参见PR

@babel/runtime 现在仅包含辅助函数,如果您需要 core-js,您可以使用 @babel/runtime-corejs2 以及转换中提供的选项。对于这两种情况,您仍然需要 @babel/plugin-transform-runtime

仅辅助函数

Shell
# install the runtime as a dependency
npm install @babel/runtime
# install the plugin as a devDependency
npm install @babel/plugin-transform-runtime --save-dev
babel.config.json
{
"plugins": ["@babel/plugin-transform-runtime"]
}

辅助函数 + 来自 core-js 的 polyfilling

因此,如果您需要在 transform-runtime 中使用 core-js 支持,您现在应该传递 corejs 选项并使用 @babel/runtime-corejs2 依赖项而不是 @babel/runtime

Shell
# install the runtime as a dependency
npm install @babel/runtime-corejs2
# install the plugin as a devDependency
npm install @babel/plugin-transform-runtime --save-dev
{
"plugins": [
- ["@babel/plugin-transform-runtime"],
+ ["@babel/plugin-transform-runtime", {
+ "corejs": 2,
+ }],
]
}

规范符合性

@babel/plugin-proposal-object-rest-spread

尾随逗号不能出现在对象的 RestElement 之后 #290 medium

var {
- ...y, // trailing comma is a SyntaxError
+ ...y
} = { a: 1 };

由于对象扩展定义了新的属性,而 Object.assign 只是设置它们,因此 Babel 更改了默认行为以更加符合规范。

JavaScript
// input
z = { x, ...y };
JavaScript
// v7 default behavior: ["proposal-object-rest-spread"]
function _objectSpread(target) { ... }

z = _objectSpread({
x
}, y);
JavaScript
// Old v6 behavior: ["proposal-object-rest-spread", { "loose": true }]
function _extends(target) { ... }

z = _extends({
x
}, y);
JavaScript
// Substitute for Object.assign: ["proposal-object-rest-spread", { "loose": true, "useBuiltIns": true }]
z = Object.assign(
{
x,
},
y
);

@babel/plugin-proposal-class-properties

默认行为已更改为以前默认情况下为“spec”的行为

JavaScript
// input
class Bork {
static a = "foo";
y;
}
JavaScript
// v7 default behavior: ["@babel/plugin-proposal-class-properties"]
var Bork = function Bork() {
Object.defineProperty(this, "y", {
enumerable: true,
writable: true,
value: void 0,
});
};

Object.defineProperty(Bork, "a", {
enumerable: true,
writable: true,
value: "foo",
});
JavaScript
// old v6 behavior: ["@babel/plugin-proposal-class-properties", { "loose": true }]
var Bork = function Bork() {
this.y = void 0;
};

Bork.a = "foo";

@babel/plugin-transform-export-extensions 拆分为两个重命名的提案

这已经很久了,但最终还是改变了。

@babel/plugin-proposal-export-default-from

JavaScript
export v from "mod";

@babel/plugin-proposal-export-namespace-from

JavaScript
export * as ns from "mod";

@babel/plugin-transform-template-literals

模板字面量修订已更新 #5523 low

有关模板字面量修订的提案,请参见。

它会导致 Babel 6 抛出 Bad character escape sequence (5:6) 错误。

JavaScript
tag`\unicode and \u{55}`;

这已在 Babel 7 中修复,并生成如下内容

JavaScript
// default
function _taggedTemplateLiteral(strings, raw) {
return Object.freeze(
Object.defineProperties(strings, { raw: { value: Object.freeze(raw) } })
);
}
var _templateObject = /*#__PURE__*/ _taggedTemplateLiteral(
[void 0],
["\\unicode and \\u{55}"]
);
tag(_templateObject);
JavaScript
// loose mode
function _taggedTemplateLiteralLoose(strings, raw) {
strings.raw = raw;
return strings;
}
var _templateObject = /*#__PURE__*/ _taggedTemplateLiteralLoose(
[void 0],
["\\unicode and \\u{55}"]
);
tag(_templateObject);

对于常规模板字面量,默认为之前的“spec”模式

JavaScript
// input
`foo${bar}`;
JavaScript
// default v7 behavior: ["@babel/plugin-transform-template-literals"]
"foo".concat(bar);
JavaScript
// old v6 behavior: ["@babel/plugin-transform-template-literals", { "loose": true }]
"foo" + bar;

@babel/plugin-proposal-decorators

为了迎接新的装饰器提案的实现,我们决定将其作为新的默认行为。这意味着要继续使用当前的装饰器语法/行为,您必须将 legacy 选项设置为 true

 {
"plugins": [
- "@babel/plugin-proposal-decorators"
+ ["@babel/plugin-proposal-decorators", { "legacy": true }]
]
}

注意:如果您正在使用包含此插件的 @babel/preset-stage-0@babel/preset-stage-1,则必须向其传递 decoratorsLegacy 选项。

@babel/plugin-proposal-pipeline-operator

默认情况下,处于变化中的较新提案将出错,并且在事物仍处于 < Stage 2 时,将要求每个人选择加入特定提案。这在这篇文章中有更详细的解释。

{
"plugins": [
- "@babel/plugin-proposal-pipeline-operator"
+ ["@babel/plugin-proposal-pipeline-operator", { "proposal": "minimal" }]
]
}

已移除 babel-plugin-transform-class-constructor-call

babel-plugin-transform-class-constructor-call 已被移除 #5119 low

TC39 决定放弃此提案。您可以将逻辑移至构造函数或静态方法中。

有关更多信息,请参见 /docs/plugins/transform-class-constructor-call/

  class Point {
constructor(x, y) {
this.x = x;
this.y = y;
}

- call constructor(x, y) {
+ static secondConstructor(x, y) {
return new Point(x, y);
}
}

let p1 = new Point(1, 2);
- let p2 = Point(3, 4);
+ let p2 = Point.secondConstructor(3, 4);

@babel/plugin-async-to-generator

我们通过将其设为一个选项,将 babel-plugin-transform-async-to-module-method 合并到常规的 async 插件中。

{
"plugins": [
- ["@babel/transform-async-to-module-method"]
+ ["@babel/transform-async-to-generator", {
+ "module": "bluebird",
+ "method": "coroutine"
+ }]
]
}

babel

放弃 babel#5293 low

此包目前会向您显示一条错误消息,要求您在 v6 中安装 babel-cli。但我认为我们可以用这个名字做些有趣的事情。

@babel/register

babel-core/register.js 已被移除 #5132 low

在 Babel 7 中,已弃用的 babel-core/register 用法已被移除;请改用独立的包 @babel/register

安装 @babel/register 作为新的依赖项

npm install --save-dev @babel/register

使用 Mocha 升级

- mocha --require babel-core/register
+ mocha --require @babel/register

@babel/register 现在也将只编译当前工作目录中的文件(这样做是为了解决符号链接的问题)。

@babel/register 选项现在被替换而不是合并

@babel/generator

放弃 quotes 选项 #5154] none

如果您希望格式化编译后的输出,可以使用 recast/prettier/escodegen/fork babel-generator。

在 v6.18.0 之前,此选项只能通过显式使用 babel-generator 获得,在 v6.18.0 中,我们公开了 parserOptsgeneratorOpts。由于该版本中存在错误,因此在 Babel 本身中,任何人都应该使用此选项。

放弃 flowUsesCommas 选项 #5123 none

目前,Flow 对象类型中有 2 种受支持的语法(,;)。

此更改只是使 babel-generator 输出 , 而不是 ;

@babel/core

移除 babel-core/src/api/browser.js #5124 none

babel-browser 在 6.0 中已被移除。如果您需要在浏览器或非 Node 环境中使用 Babel,请使用 @babel/standalone

Babel 将返回 filename 作为绝对路径 #8044

@babel/preset-env

loose 模式现在将自动排除 typeof-symbol 转换(许多使用 loose 模式的项目都在这样做)。