跳至主要内容

升级到 Babel 7(API)

在升级到 Babel 7 时,请参考此文档。

另请查看 v7 迁移指南 以了解其他用户级别的更改。

所有 Babel 包

NodeJS 支持

high

已放弃对 Node.js 0.10 和 0.12 的支持,因为这两个版本均已停止维护。

导出更改

medium

在 Babel 包上放弃使用 add-module-exports 插件。之前必须使用它来防止导出发生重大更改。如果您在库中导入 Babel 包,则在使用 require 而不是 import 时,可能需要使用 .default

@babel/core

ast 更改为默认情况下为 false 以提高性能(大多数工具未使用它) babel/babel#7436

已删除公开但未记录的 Pipeline 类。最好直接使用 @babel/core 中公开的转换方法 babel/babel#5376

已删除 babel.util.* 辅助方法,并将 util.EXTENSIONS 移至 babel.DEFAULT_EXTENSIONS babel/babel#5487

如果文件匹配 ignore 模式或未能匹配 only 模式,则对 babel.transform 或任何其他转换函数的调用可能会返回 null babel/babel#5487

已删除 state.file.opts 上公开的 opts.basename 选项。如果您需要它,最好从 opts.filename 中构建它 babel/babel#5467

删除了 resolveModuleSource。我们建议使用 babel-plugin-module-resolver@3 的“resolvePath”选项 babel/babel#6343

删除了 babel.analyse,因为它只是 babel.transform 的别名

删除了 path.mark(),因为我们没有使用它,并且它可以在您自己的插件中实现。

删除了 babel.metadata,因为生成的插件元数据始终包含在输出结果中。

删除了 path.hub.file.addImport。您可以改用 @babel/helper-module-imports 模块。

+  import { addDefault } from "@babel/helper-module-imports";
function importModule(pkgStore, name, path) {
- return path.hub.file.addImport(resolvePath(pkgStore, name, path), 'default', name);
+ return addDefault(path, resolvePath(pkgStore, name, path), { nameHint: name });
}

配置更改

我们对配置查找的工作方式进行了一些重大更改

默认情况下,在为给定文件搜索 .babelrc 文件时,在 package.json 处停止。

对于任何特定文件,Babel v6 会一直向上查找目录层次结构,直到找到配置文件。这意味着您的项目可能会中断,因为它使用了在包根目录之外找到的配置文件,例如在主目录中。

添加了对 babel.config.js 文件的支持,类似于 Webpack 的做法

因为这会破坏 monorepo 的工作方式(包括 Babel 本身),所以我们引入了一个新的配置文件,它基本上消除了配置的层次结构性质。

其中包含一个 root 选项,默认情况下为当前工作目录,以便它查找文件。它也不是相对加载的,因此它将正确处理符号链接,而之前您可能在 webpack 中硬编码了路径。

有关更多信息,请查看 babel.config.js 文档:项目范围的配置

此文件与新的 overrides 属性和 env 相结合,使您可以拥有一个配置文件,该文件可以适用于项目中的所有文件,而不是每个文件夹多个配置文件。

我们还默认排除 node_modules,并且仅在根目录中查找,除非您选择设置 .babelrcRoots 选项的数组,例如 "babelrcRoots": [".", "node_modules/pkgA"]

断言 Babel 版本 #7450

插件可以检查它是否已加载特定版本的 Babel。API 将公开一个 assertVersion 方法,您可以在其中传入 semver。

declare 辅助函数用于保持与 v6 的向后兼容性。

JavaScript
import { declare } from "@babel/helper-plugin-utils";

export default declare(api => {
api.assertVersion(7);
// ...
});

Babel 插件/预设

它当前将 babel 对象、插件/预设选项和 dirname 作为第一个参数

JavaScript
module.exports = function(api, options, dirname) {};

babel-parser(称为 Babylon)

删除了 * 插件选项 #301 低

这最初是在 v6.14.1(2016 年 11 月 17 日)中添加的,因此不太可能有人使用它。

此包罗万象的选项已删除;相反,您应该明确决定要激活哪些插件。

我们认为这对工具来说是个好主意,因此它们不必不断更新其配置,但这也意味着我们不能轻易做出重大更改。

之前

JavaScript
babelParser.parse(code, {
plugins: ["*"],
});

您可以使用以下方法获得旧行为

JavaScript
babelParser.parse(code, {
plugins: [
"asyncGenerators",
"classProperties",
"decorators",
"doExpressions",
"dynamicImport",
"exportExtensions",
"flow",
"functionBind",
"functionSent",
"jsx",
"objectRestSpread",
],
});

请参阅 Babylon 的 插件选项

decorators 插件重命名为 decorators-legacy 中

它已重命名为与 @babel/plugin-proposal-decoratorslegacy 选项一致。已实现新的 decorators 插件,它实现了新的装饰器提案。

这两个版本的提案具有不同的语法,因此强烈建议使用 decorators-legacy,直到 Babel 实现新的语义。

删除了 classConstructorCall 插件 #291 低

@babel/traverse

删除对流绑定的支持 babel/babel#6528

进行此更改的原因是 declare var foo 不会引入新的局部绑定,而是表示全局绑定。

getFunctionParent 将不再返回 Program,请改用 getProgramParent #5923低

名为 getFunctionParent 的函数也返回 Program 是没有意义的,因此将其删除了。

要获得等效的行为,您需要进行如下更改

- path.scope.getFunctionParent()
+ path.scope.getFunctionParent() || path.scope.getProgramParent()

路径替换/删除 API 现在返回一个新路径数组 低

例如,使用 Path#insertBeforePath#replaceWith 现在将始终返回新插入/替换的路径数组。

JavaScript
const node = t.nullLiteral();
const [replaced] = path.replaceWith(node);
replace.node === node; // => true

当将多个节点插入到某个更高级别的作用域中时,这尤其有用,因为您可以立即在节点的新 Path 上调用 Path API。

JavaScript
const parent = path.findParent(() => /* some selection criteria */);
const helperPaths = path.unshiftContainer("body", helpers);
// helperPaths can now be referenced, manipulated, etc.

AST 更改

添加 InterpreterDirective 节点 #7928

Babylon 已经解析了“shebang”(#!env node),但将其放在 Program 节点中的注释中。现在,我们正在为它创建一个实际的节点。

Program 节点添加一个新的 interpreter 字段。

JavaScript
extend interface Program {
interpreter: InterpreterDirective;
}

添加 InterpreterDirective 节点

JavaScript
interface InterpreterDirective <: Node {
type: "InterpreterDirective";
value: string;
}

JSX* 和 TS* 节点构建器(来自 @babel/types 包)已重命名

大小写已更改:jsxts 现在为小写。

- t.jSXIdentifier()
+ t.jsxIdentifier()

通常,我们使用 TypeAnnotation 区分 Flow 的节点类型,使用 TSTypeAnnotation 区分 TypeScript 的节点类型,因此对于共享类型节点,TypeScript 具有 TS 前缀。

ArrowFunctionExpression 中删除了 .expression 字段

删除了 expression 字段,以消除两个不同的真实来源,并且需要插件手动保持它们同步。您现在可以简单地检查函数体是否是 BlockStatement

  return {
visitor: {
ArrowFunctionExpression({ node }) {
- if (node.expression) {
+ if (node.body.type !== "BlockStatement") {
// () => foo;
}
}
}
};

已删除令牌

在以前的版本中,tokens 始终附加到顶层的 AST。在最新版本的 @babel/parser 中,我们删除了此行为,并默认将其禁用以提高解析器的性能。babel 本身的所有用法都已删除,并且 @babel/generator 不再使用令牌进行漂亮打印。

如果您的 babel 插件当前使用 tokens,请评估它是否仍然必要,并在可能的情况下尝试删除使用。如果您的插件确实依赖于获取令牌,您可以重新激活它,但请仅在没有其他方法的情况下才考虑这样做,因为这会损害用户的性能。

要激活,您需要将 babylon 的 tokens 选项设置为 true。您可以直接从您的插件中执行此操作。

JavaScript
export default function() {
return {
manipulateOptions(opts, parserOpts) {
parserOpts.tokens = true;
},
...
};
}

已重命名

以下节点已重命名

名称 6.x名称 7.x示例PR
ExistentialTypeParamExistsTypeAnnotationtype A = B<*>;#322
NumericLiteralTypeAnnotationNumberLiteralTypeAnnotationtype T = 0;#332

除了 AST-Nodes 之外,@babel/types 中的所有相应函数也已重命名。

 import * as t from "@babel/types";

return {
- ExistentialTypeParam(path) {
- const parent = path.findParent((path) => path.isExistentialTypeParam());
- t.isExistentialTypeParam(parent);
+ ExistsTypeAnnotation(path) {
+ const parent = path.findParent((path) => path.isExistsTypeAnnotation());
+ t.isExistsTypeAnnotation(parent);

- return t.existentialTypeParam();
+ return t.existsTypeAnnotation();
},
- NumericLiteralTypeAnnotation(path) {
- const parent = path.findParent((path) => path.isNumericLiteralTypeAnnotation());
- t.isNumericLiteralTypeAnnotation(parent);
+ NumberLiteralTypeAnnotation(path) {
+ const parent = path.findParent((path) => path.isNumberLiteralTypeAnnotation());
+ t.isNumberLiteralTypeAnnotation(parent);

- return t.numericLiteralTypeAnnotation();
+ return t.numberLiteralTypeAnnotation();
}
};

已替换

在以下 AST-Nodes 上,字段 variance 的值已从简单的字符串值更改为其自己的名为 Variance 的 AST-Node。 #333

仅当在 babylon 中启用 flow 插件时,该字段才可用。

  • ObjectProperty
  • ObjectMethod
  • 赋值属性
  • 类方法
  • 类属性
  • 属性

新的 Variance 节点的类型如下所示

JavaScript
type VarianceNode = {
type: "Variance",
kind: "plus" | "minus",
};
 return {
Property({ node }) {
- if (node.variance === "plus") {
+ if (node.variance.kind === "plus") {
...
- } else if (node.variance === "minus") {
+ } else if (node.variance.kind === "minus") {
...
}
}
};

位置变化

ObjectTypeIndexer 的位置信息已更改为不包含分号。这样做是为了与 flow-parser 保持一致并具有相同的位置信息。 #228

示例

JavaScript
var a: { [a: number]: string };
 {
"type": "ObjectTypeIndexer",
"start": 9,
- "end": 29,
+ "end": 28,
"loc": {
"start": {
"line": 1,
"column": 9,
},
"end": {
"line": 1,
- "column": 29
+ "column": 28
}
}
}

移除

ForAwaitStatement

AST 节点 ForAwaitStatement 已被移除,并由 ForOfStatement 节点中的 await 字段代替 #349

 interface ForOfStatement <: ForInStatement {
type: "ForOfStatement";
+ await: boolean;
}
 return {
- ForAwaitStatement(path) {
- ...
+ ForOfStatement(path) {
+ if (path.node.await) {
+ ...
+ }
}
};

RestProperty & SpreadProperty

两个 AST 节点 RestPropertySpreadProperty 已被移除,转而重用 RestElementSpreadElement #384

 return {
SpreadElement(path) {
- ...
- },
- SpreadProperty(path) {
- ...
+ if (path.parentPath.isObjectExpression()) {
+ ...
+ } else if (path.parentPath.isArrayExpression()) {
+ ...
+ }
},
RestElement(path) {
- ...
- },
- RestProperty(path) {
- ...
+ if (path.parentPath.isObjectPattern()) {
+ ...
+ } else if (path.parentPath.isArrayPattern()) {
+ ...
+ }
}
};

有关更多信息,请参阅我们针对 Babel 的升级 PRBabylon AST 规范