升级到 Babel 7(API)
在升级到 Babel 7 时,请参考此文档。
另请查看 v7 迁移指南 以了解其他用户级别的更改。
所有 Babel 包
NodeJS 支持
已放弃对 Node.js 0.10 和 0.12 的支持,因为这两个版本均已停止维护。
导出更改
在 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 的向后兼容性。
import { declare } from "@babel/helper-plugin-utils";
export default declare(api => {
api.assertVersion(7);
// ...
});
Babel 插件/预设
它当前将 babel
对象、插件/预设选项和 dirname
作为第一个参数
module.exports = function(api, options, dirname) {};
babel-parser
(称为 Babylon)
删除了
*
插件选项 #301
这最初是在 v6.14.1(2016 年 11 月 17 日)中添加的,因此不太可能有人使用它。
此包罗万象的选项已删除;相反,您应该明确决定要激活哪些插件。
我们认为这对工具来说是个好主意,因此它们不必不断更新其配置,但这也意味着我们不能轻易做出重大更改。
之前
babelParser.parse(code, {
plugins: ["*"],
});
您可以使用以下方法获得旧行为
babelParser.parse(code, {
plugins: [
"asyncGenerators",
"classProperties",
"decorators",
"doExpressions",
"dynamicImport",
"exportExtensions",
"flow",
"functionBind",
"functionSent",
"jsx",
"objectRestSpread",
],
});
请参阅 Babylon 的 插件选项。
将
decorators
插件重命名为decorators-legacy
它已重命名为与 @babel/plugin-proposal-decorators
的 legacy
选项一致。已实现新的 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#insertBefore
或 Path#replaceWith
现在将始终返回新插入/替换的路径数组。
const node = t.nullLiteral();
const [replaced] = path.replaceWith(node);
replace.node === node; // => true
当将多个节点插入到某个更高级别的作用域中时,这尤其有用,因为您可以立即在节点的新 Path
上调用 Path
API。
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
字段。
extend interface Program {
interpreter: InterpreterDirective;
}
添加 InterpreterDirective
节点
interface InterpreterDirective <: Node {
type: "InterpreterDirective";
value: string;
}
JSX* 和 TS* 节点构建器(来自 @babel/types 包)已重命名
大小写已更改:jsx
和 ts
现在为小写。
- 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。您可以直接从您的插件中执行此操作。
export default function() {
return {
manipulateOptions(opts, parserOpts) {
parserOpts.tokens = true;
},
...
};
}
已重命名
以下节点已重命名
名称 6.x | 名称 7.x | 示例 | PR |
---|---|---|---|
ExistentialTypeParam | ExistsTypeAnnotation | type A = B<*>; | #322 |
NumericLiteralTypeAnnotation | NumberLiteralTypeAnnotation | type 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
节点的类型如下所示
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
示例
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 节点 RestProperty
和 SpreadProperty
已被移除,转而重用 RestElement
和 SpreadElement
#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 的升级 PR和Babylon AST 规范。