Skip to main content

升级到 Babel 8 (API)

本文档列出了 Babel 8.0.0 中引入的重大更改,以及从 Babel 7.0.0 升级时如何调整 Babel 的使用以适应这些更改。本文档面向直接使用 Babel API 的开发者,例如 Babel 插件作者或使用 Babel 作为库的项目作者。

¥This document lists the breaking changes introduced in Babel 8.0.0, and how to adapt your usage of Babel to them when upgrading from Babel 7.0.0. This document is intended for developers using Babel's API directly, such as Babel plugin authors, or authors of projects that use Babel as a library.

信息

请先查看 Babel 8 迁移指南,了解面向用户的重大变更。

¥Check out the Babel 8 migration guide first to learn about user-facing breaking changes.

AST 变更

¥AST Changes

JavaScript 节点

¥JavaScript nodes

high

  • 将动态 import() 表示为 ImportExpression 节点(#15682#16114)。

    ¥Represent dynamic import() with an ImportExpression node (#15682, #16114).

    // Example input
    import("foo", options);

    // AST in Babel 7
    {
    type: "CallExpression",
    callee: { type: "Import" },
    arguments: [
    StringLiteral("foo"),
    Identifier("options")
    ]
    }

    // AST in Babel 8
    {
    type: "ImportExpression",
    source: StringLiteral("foo"),
    options: Identifier("options")
    }

    迁移:我们鼓励你使用新的 AST(从 v7.23.0 开始)测试你的 Babel 插件,并在 Babel 配置中指定 { parserOpts: { createImportExpressions: true } }。对于使用依赖于旧版 import() AST 的 Babel 插件的终端用户,可以将 createImportExpressions 设置为 false。请注意,Babel 7 import() AST 现已弃用,它不支持新的 ES 功能,例如 源短语导入。我们将在 Babel 9 中移除 createImportExpressions 解析器选项。

    ¥Migration: You are encouraged to test your Babel plugins with the new AST, starting from v7.23.0, specifying { parserOpts: { createImportExpressions: true } } in the Babel config. For end users utilizing Babel plugins that rely on the legacy import() AST, it is possible to set createImportExpressions to false. Note that the Babel 7 import() AST is now considered deprecated, it does not support new ES features such as Source Phrase Imports. We will remove the createImportExpressions parser option in Babel 9.

medium

  • 使用 bigint 代替 BigIntLiteral.value,而不是字符串(#17378

    ¥ Use bigint for BigIntLiteral.value, rather than a string(#17378)

    // Example input
    0xff01_0000_0000_0000_0000_0000_0000_0001n

    // AST in Babel 7
    {
    type: "BigIntLiteral",
    value: "0xff010000000000000000000000000001",
    extra: {
    rawValue: "0xff010000000000000000000000000001",
    raw: "0xff01_0000_0000_0000_0000_0000_0000_0001n",
    }
    }

    // AST in Babel 8
    {
    type: "BigIntLiteral",
    value: 338958331222012082418099330867817086977n,
    extra: {
    rawValue: 338958331222012082418099330867817086977n,
    raw: "0xff01_0000_0000_0000_0000_0000_0000_0001n"
    }
    }

    迁移:此项变更与我们处理 NumericLiteral 的方式一致。如果你想在 Babel 7 中访问字符串表示,请调用 toString() 的 bigint 实例方法。请注意,内置 JavaScript 方法 JSON.stringify 无法序列化 bigint。如果你想将 Babel 8 AST 存储为 JSON,可以使用 提供你自己的 bigint 序列化器

    ¥Migration: This change aligns with how we handle NumericLiteral. If you want to access string representation in Babel 7, call the toString() bigint instance method. Note that the builtin JavaScript method JSON.stringify can not serialize bigint. If you want to store the Babel 8 AST as JSON, you can provide your own bigint serializer.

TypeScript 节点

¥TypeScript nodes

我们对 TypeScript 特定的 AST 节点所做的大部分更改都是为了减少与 @typescript-eslint 项目 AST 形状的差异。这将使编写 ESLint 规则变得更容易,当不依赖类型信息时,这些规则可以同时与 @typescript-eslint/parser@babel/eslint-parser 兼容。

¥Most of the changes to our TypeScript-specific AST nodes are to reduce the differences with the AST shape of the @typescript-eslint project. This will make it easier to write ESLint rules that, when not depending on type information, can work both with @typescript-eslint/parser and @babel/eslint-parser.

medium

  • 使用标识符代替 TSTypeParameter.name,而不是纯字符串(#12829

    ¥ Use an identifier for TSTypeParameter.name, rather than a plain string (#12829)

    input.ts
    // T is a TSTypeParameter
    function process<T>(input: T): T {}

    // AST in Babel 7
    {
    type: "TSTypeParameter",
    name: "T",
    }

    // AST in Babel 8
    {
    type: "TSTypeParameter",
    name: { type: "Identifier", name: "T" },
    }
  • 允许将 ThisExpression 用作 TSTypeQuery.exprName,而不是 this 标识符 (#17059)

    ¥Allow ThisExpression as TSTypeQuery.exprName, rather than a this identifier (#17059)

    input.ts
    function fn() {
    // `typeof this` is a TSTypeQuery
    var self: typeof this
    }

    // AST in Babel 7
    {
    type: "TSTypeQuery",
    exprName: { type: "Identifier", name: "this" }
    }

    // AST in Babel 8
    {
    type: "TSTypeQuery",
    exprName: { type: "ThisExpression" }
    }
  • TSImportEqualsDeclaration 导出为 ExportNamedDeclaration 进行解析(#17073

    ¥Parse exporting TSImportEqualsDeclaration as an ExportNamedDeclaration (#17073)

    请注意,isExport 字段也已被移除。对于任何 TSImportEqualsDeclaration NodePath p,使用 p.parentPath.isExportNamedDeclaration() 检测它是否位于 export 关键字之后。

    ¥Note that the isExport field is also removed. For any TSImportEqualsDeclaration NodePath p, use p.parentPath.isExportNamedDeclaration() to detect whether it is following an export keyword.

    input.ts
    export import foo = require("foo")

    // AST in Babel 7
    {
    type: "TSImportEqualsDeclaration",
    importKind: "value"
    isExport: true,
    id: Identifier("foo"),
    moduleReference: {
    type: "TSExternalModuleReference",
    expression: StringLiteral("foo")
    }
    }

    // AST in Babel 8
    {
    type: "ExportNamedDeclaration",
    declaration: {
    type: "TSImportEqualsDeclaration",
    importKind: "value"
    id: Identifier("foo"),
    moduleReference: {
    type: "TSExternalModuleReference",
    expression: StringLiteral("foo")
    }
    },
    specifiers: []
    }
  • TSCallSignatureDeclarationTSConstructSignatureDeclarationTSFunctionTypeTSConstructorTypeTSMethodSignature#9231#13709)中的 parameters 重命名为 params,将 typeAnnotation 重命名为 returnType

    ¥Rename parameters to params and typeAnnotation to returnType in TSCallSignatureDeclaration, TSConstructSignatureDeclaration, TSFunctionType, TSConstructorType and TSMethodSignature (#9231, #13709)

    TSCallSignatureDeclaration
    input.ts
    interface Foo {
    (x: number): string;
    }

    // AST in Babel 7
    {
    type: "TSCallSignatureDeclaration",
    parameters: [
    { type: "Identifier", name: "x", typeAnnotation: { type: "TSNumberKeyword" } }
    ],
    typeAnnotation: {
    type: "TSTypeAnnotation",
    typeAnnotation: { type: "TSStringKeyword" }
    }
    }

    // AST in Babel 8
    {
    type: "TSCallSignatureDeclaration",
    params: [
    { type: "Identifier", name: "x", typeAnnotation: { type: "TSNumberKeyword" } }
    ],
    retutnType: {
    type: "TSTypeAnnotation",
    typeAnnotation: { type: "TSStringKeyword" }
    }
    }
    TSConstructSignatureDeclaration
    input.ts
    interface Foo {
    new (x: number): string;
    }

    // AST in Babel 7
    {
    type: "TSConstructSignatureDeclaration",
    parameters: [
    { type: "Identifier", name: "x", typeAnnotation: { type: "TSNumberKeyword" } }
    ],
    typeAnnotation: {
    type: "TSTypeAnnotation",
    typeAnnotation: { type: "TSStringKeyword" }
    }
    }

    // AST in Babel 8
    {
    type: "TSConstructSignatureDeclaration",
    params: [
    { type: "Identifier", name: "x", typeAnnotation: { type: "TSNumberKeyword" } }
    ],
    retutnType: {
    type: "TSTypeAnnotation",
    typeAnnotation: { type: "TSStringKeyword" }
    }
    }
    TSMethodSignature
    input.ts
    interface Foo {
    foo(x: number): string;
    }

    // AST in Babel 7
    {
    type: "TSMethodSignature",
    key: Identifier("foo"),
    parameters: [
    { type: "Identifier", name: "x", typeAnnotation: { type: "TSNumberKeyword" } }
    ],
    typeAnnotation: {
    type: "TSTypeAnnotation",
    typeAnnotation: { type: "TSStringKeyword" }
    }
    }

    // AST in Babel 8
    {
    type: "TSMethodSignature",
    key: Identifier("foo"),
    params: [
    { type: "Identifier", name: "x", typeAnnotation: { type: "TSNumberKeyword" } }
    ],
    retutnType: {
    type: "TSTypeAnnotation",
    typeAnnotation: { type: "TSStringKeyword" }
    }
    }
    TSFunctionType
    input.ts
    type Bar = (x: number) => string;

    // AST in Babel 7
    {
    type: "TSFunctionType",
    parameters: [
    { type: "Identifier", name: "x", typeAnnotation: { type: "TSNumberKeyword" } }
    ],
    typeAnnotation: {
    type: "TSTypeAnnotation",
    typeAnnotation: { type: "TSStringKeyword" }
    }
    }

    // AST in Babel 8
    {
    type: "TSFunctionType",
    params: [
    { type: "Identifier", name: "x", typeAnnotation: { type: "TSNumberKeyword" } }
    ],
    retutnType: {
    type: "TSTypeAnnotation",
    typeAnnotation: { type: "TSStringKeyword" }
    }
    }
    TSConstructorType
    input.ts
    type Bar = (x: number) => string;

    // AST in Babel 7
    {
    type: "TSConstructorType",
    parameters: [
    { type: "Identifier", name: "x", typeAnnotation: { type: "TSNumberKeyword" } }
    ],
    typeAnnotation: {
    type: "TSTypeAnnotation",
    typeAnnotation: { type: "TSStringKeyword" }
    }
    }

    // AST in Babel 8
    {
    type: "TSConstructorType",
    params: [
    { type: "Identifier", name: "x", typeAnnotation: { type: "TSNumberKeyword" } }
    ],
    retutnType: {
    type: "TSTypeAnnotation",
    typeAnnotation: { type: "TSStringKeyword" }
    }
    }
  • CallExpressionJSXOpeningElementNewExpressionOptionalCallExpressionTSImportTypeTSInstantiationExpressionTSTypeQueryTSTypeReference#16679#17008#17012#17020#17042)中的 typeParameters 重命名为 typeArguments

    ¥ Rename typeParameters to typeArguments in CallExpression, JSXOpeningElement, NewExpression, OptionalCallExpression, TSImportType, TSInstantiationExpression, TSTypeQuery and TSTypeReference (#16679, #17008, #17012, #17020, #17042)

    CallExpression
    input.ts
    fn<string>()

    // AST in Babel 7
    {
    type: "CallExpression",
    callee: Identifier("fn"),
    arguments: [],
    typeParameters: {
    type: "TSTypeParameterInstantiation",
    params: [{
    type: "TSStringKeyword"
    }]
    }
    }

    // AST in Babel 8
    {
    type: "CallExpression",
    callee: Identifier("fn"),
    arguments: [],
    typeArguments: {
    type: "TSTypeParameterInstantiation",
    params: [{
    type: "TSStringKeyword"
    }]
    }
    }
    JSXOpeningElement
    input.ts
    <Component<string>/>

    // AST in Babel 7
    {
    type: "JSXOpeningElement",
    name: JSXIdentifier("Component"),
    attributes: [],
    selfClosing: true,
    typeParameters: {
    type: "TSTypeParameterInstantiation",
    params: [{
    type: "TSStringKeyword"
    }]
    }
    }

    // AST in Babel 8
    {
    type: "JSXOpeningElement",
    name: JSXIdentifier("Component"),
    attributes: [],
    selfClosing: true,
    typeArguments: {
    type: "TSTypeParameterInstantiation",
    params: [{
    type: "TSStringKeyword"
    }]
    }
    }
    NewExpression
    input.ts
    new Component<string>()

    // AST in Babel 7
    {
    type: "NewExpression",
    callee: Identifier("Component"),
    arguments: [],
    typeParameters: {
    type: "TSTypeParameterInstantiation",
    params: [{
    type: "TSStringKeyword"
    }]
    }
    }

    // AST in Babel 8
    {
    type: "NewExpression",
    callee: Identifier("Component"),
    arguments: [],
    typeArguments: {
    type: "TSTypeParameterInstantiation",
    params: [{
    type: "TSStringKeyword"
    }]
    }
    }
    OptionalCallExpression
    input.ts
    fn?.<string>()

    // AST in Babel 7
    {
    type: "OptionalCallExpression",
    callee: Identifier("fn"),
    arguments: [],
    optional: true,
    typeParameters: {
    type: "TSTypeParameterInstantiation",
    params: [{
    type: "TSStringKeyword"
    }]
    }
    }

    // AST in Babel 8
    {
    type: "OptionalCallExpression",
    callee: Identifier("fn"),
    arguments: [],
    optional: true,
    typeArguments: {
    type: "TSTypeParameterInstantiation",
    params: [{
    type: "TSStringKeyword"
    }]
    }
    }
    TSImportType
    input.ts
    var arr: import("./Array")<string>

    // AST in Babel 7
    {
    type: "TSImportType",
    argument: StringLiteral("./Array"),
    typeParameters: {
    type: "TSTypeParameterInstantiation",
    params: [{
    type: "TSStringKeyword"
    }]
    }
    }

    // AST in Babel 8
    {
    type: "TSImportType",
    argument: {
    type: "TSLiteralType",
    literal: StringLiteral("./Array")
    },
    typeArguments: {
    type: "TSTypeParameterInstantiation",
    params: [{
    type: "TSStringKeyword"
    }]
    }
    }
    TSInstantiationExpression
    input.ts
    fn<string>

    // AST in Babel 7
    {
    type: "TSInstantiationExpression",
    expression: Identifier("fn"),
    typeParameters: {
    type: "TSTypeParameterInstantiation",
    params: [{
    type: "TSStringKeyword"
    }]
    }
    }

    // AST in Babel 8
    {
    type: "TSInstantiationExpression",
    expression: Identifier("fn"),
    typeArguments: {
    type: "TSTypeParameterInstantiation",
    params: [{
    type: "TSStringKeyword"
    }]
    }
    }
    TSTypeQuery
    input.ts
    var arr: typeof Array<string>;

    // AST in Babel 7
    {
    type: "TSTypeQuery",
    exprName: Identifier("Array"),
    typeParameters: {
    type: "TSTypeParameterInstantiation",
    params: [{
    type: "TSStringKeyword"
    }]
    }
    }

    // AST in Babel 8
    {
    type: "TSTypeQuery",
    exprName: Identifier("Array"),
    typeArguments: {
    type: "TSTypeParameterInstantiation",
    params: [{
    type: "TSStringKeyword"
    }]
    }
    }
    TSTypeReference
    input.ts
    var arr: Array<string>;

    // AST in Babel 7
    {
    type: "TSTypeReference",
    typeName: Identifier("Array"),
    typeParameters: {
    type: "TSTypeParameterInstantiation",
    params: [{
    type: "TSStringKeyword"
    }]
    }
    }

    // AST in Babel 8
    {
    type: "TSTypeReference",
    typeName: Identifier("Array"),
    typeArguments: {
    type: "TSTypeParameterInstantiation",
    params: [{
    type: "TSStringKeyword"
    }]
    }
    }
  • ClassDeclarationClassExpression#16679#16997)中的 superTypeParameters 重命名为 superTypeArguments

    ¥Rename superTypeParameters to superTypeArguments in ClassDeclaration and ClassExpression (#16679, #16997)

    input.ts
    class X extends Y<string> {}

    // AST in Babel 7
    {
    type: "ClassDeclaration",
    id: Identifier("X"),
    superClass: Identifier("Y"),
    superTypeParameters: {
    type: "TSTypeParameterInstantiation",
    params: [{
    type: "TSStringKeyword"
    }]
    }
    }

    // AST in Babel 8
    {
    type: "ClassDeclaration",
    id: Identifier("X"),
    superClass: Identifier("Y"),
    superTypeArguments: {
    type: "TSTypeParameterInstantiation",
    params: [{
    type: "TSStringKeyword"
    }]
    }
    }
  • typeParameterTSMappedType#16733)中拆分出来。

    ¥ Split typeParameter of TSMappedType (#16733).

    TSMappedType 节点中,typeParameter 属性被展平为 TSMappedType 本身的 keyconstraint 属性。

    ¥In TSMappedType nodes, the typeParameter property is flattened as key and constraint properties of TSMappedType itself.

    input.ts
    let map1: { [P in string]: number; };

    // AST in Babel 7
    {
    type: "TSMappedType",
    typeParameter: {
    type: "TypeParameter",
    name: Identifier("P"),
    constraint: TSStringKeyword()
    },
    typeAnnotation: TSNumberKeyword(),
    }

    // AST in Babel 8
    {
    type: "TSMappedType",
    key: Identifier("P"),
    constraint: TSStringKeyword()
    typeAnnotation: TSNumberKeyword(),
    }
  • TSExpressionWithTypeArguments 拆分为 TSClassImplementsTSInterfaceHeritage#16731)。

    ¥Split TSExpressionWithTypeArguments into TSClassImplements and TSInterfaceHeritage (#16731).

    新节点也使用 typeArguments 而不是 typeParameters#17017)。如果 expression 是 TS 限定名称(例如 a.b),它将被解析为 MemberExpression#17139)。

    ¥The new nodes also use typeArguments instead of typeParameters (#17017). If the expression is a TS qualified name (e.g. a.b), it will be parsed as a MemberExpression (#17139).

    TSClassImplements
    input.ts
    class C implements X<T> {}

    // AST in Babel 7
    {
    type: "ClassDeclaration",
    id: Identifier("C"),
    implements: [
    {
    type: "TSExpressionWithTypeArguments",
    expression: Identifier("X"),
    typeParameters: {
    type: "TSTypeParameterInstantiation",
    params: [TSTypeReference(Identifier("T"))]
    }
    }
    ],
    body: ClassBody([]),
    }

    // AST in Babel 8
    {
    type: "ClassDeclaration",
    id: Identifier("C"),
    implements: [
    {
    type: "TSClassImplements",
    expression: Identifier("X"),
    typeArguments: {
    type: "TSTypeParameterInstantiation",
    params: [TSTypeReference(Identifier("T"))]
    }
    }
    ],
    body: ClassBody([]),
    }
    TSInterfaceHeritage
    input.ts
    interface I extends X<T> {}

    // AST in Babel 7
    {
    type: "TSInterfaceDeclaration",
    id: Identifier("I"),
    extends: [
    {
    type: "TSExpressionWithTypeArguments",
    expression: Identifier("X"),
    typeParameters: {
    type: "TSTypeParameterInstantiation",
    params: [TSTypeReference(Identifier("T"))]
    }
    }
    ],
    body: TSInterfaceBody([]),
    }

    // AST in Babel 8
    {
    type: "TSInterfaceDeclaration",
    id: Identifier("I"),
    extends: [
    {
    type: "TSInterfaceHeritage",
    expression: Identifier("X"),
    typeArguments: {
    type: "TSTypeParameterInstantiation",
    params: [TSTypeReference(Identifier("T"))]
    }
    }
    ],
    body: TSInterfaceBody([]),
    }
    Qualified name
    input.ts
    class C implements X.Y {}

    // AST in Babel 7
    {
    type: "ClassDeclaration",
    id: Identifier("C"),
    implements: [
    {
    type: "TSExpressionWithTypeArguments",
    expression: {
    type: "TSQualifiedName",
    left: Identifier("X"),
    right: Identifier("Y")
    }
    }
    ],
    body: ClassBody([]),
    }

    // AST in Babel 8
    {
    type: "ClassDeclaration",
    id: Identifier("C"),
    implements: [
    {
    type: "TSClassImplements",
    expression: {
    type: "MemberExpression",
    object: Identifier("X"),
    property: Identifier("Y"),
    computed: false
    }
    }
    ],
    body: ClassBody([]),
    }
  • TSImportTypeargument 封装在 TSLiteralType 节点中(#17046

    ¥ Wrap the argument of TSImportType within a TSLiteralType (#17046)

    TSImportType 还使用 typeArguments 而不是 typeParameters#17042)。有关示例,请参阅 此处

    ¥The TSImportType also uses typeArguments instead of typeParameters (#17042). See here for an example.

    input.ts
      var arr: import("./Array")

    // AST in Babel 7
    {
    type: "TSImportType",
    argument: StringLiteral("./Array")
    }

    // AST in Babel 8
    {
    type: "TSImportType",
    argument: {
    type: "TSLiteralType",
    literal: StringLiteral("./Array")
    }
    }
  • TSEnumDeclarationmembers 封装在 TSEnumBody 节点中(#16979

    ¥ Wrap the members of TSEnumDeclaration within a TSEnumBody node (#16979)

    input.ts
    // Example input
    enum ColorType {
    Red,
    Green,
    Blue,
    }

    // AST in Babel 7
    {
    type: "TSEnumDeclaration",
    id: Identifier("ColorType")
    members: [
    EnumMember("Red"),
    EnumMember("Green"),
    EnumMember("Blue")
    ]
    }

    // AST in Babel 8
    {
    type: "TSEnumDeclaration",
    id: Identifier("ColorType")
    body: {
    type: "TSEnumBody",
    members: [
    EnumMember("Red"),
    EnumMember("Green"),
    EnumMember("Blue")
    ]
    }
    }
  • 当至少有一个插值位置时,创建 TSTemplateLiteralType

    ¥Create TSTemplateLiteralType when there is at least one interpolated position

    请注意,当没有插值位置时,AST 不会更改,例如,作为模板字面量类型的 foo 仍然会被解析为 TSLiteralType 中的 TemplateLiteral 节点。

    ¥Note that the AST is not changed when there is no interpolated position, e.g. `foo` as a template literal type is still parsed as a TemplateLiteral node within a TSLiteralType.

    input.ts
    type World = "world";
    // `hello ${World}` is a template literal type
    type Greeting = `hello ${World}`;

    // AST in Babel 7
    {
    type: "TSLiteralType",
    literal: {
    type: "TemplateLiteral",
    expressions: [{
    type: "TSTypeReference",
    typeName: Identifier("World")
    }],
    quasis: [
    TemplateElement("hello "),
    TemplateElement("")
    ]
    }
    }

    // AST in Babel 8
    {
    type: "TSTemplateLiteralType",
    types: [{
    type: "TSTypeReference",
    typeName: Identifier("World")
    }],
    quasis: [
    TemplateElement("hello "),
    TemplateElement("")
    ]
    }
  • 当同时启用 estreetypescript 解析器插件时,创建 TSAbstractMethodDefinitionTSPropertyDefinition#16679#17014)。

    ¥Create TSAbstractMethodDefinition and TSPropertyDefinition when both estree and typescript parser plugins are enabled (#16679, #17014)

    迁移:此项重大变更是为了使库和 ESLint 插件能够同时与 typescript-eslint@babel/eslint-parser 兼容。对于大多数 Babel 插件开发者,你可以放心地忽略此更改,因为它不会影响 TypeScript 转换和代码修改。也就是说,如果你尝试使用 @babel/eslint-parser 开发自定义 ESLint 规则,此更改将使 Babel AST 与 typescript-eslint AST 保持一致。

    ¥Migration: This breaking change is part of the efforts to libraries and ESLint plugins that can work both with typescript-eslint and @babel/eslint-parser. For most Babel plugin developers you can safely ignore this change as it does not affect the typescript transform and codemod. That said, if you are trying to develop a custom ESLint rule with @babel/eslint-parser, this change aligns the Babel AST to the typescript-eslint AST.

  • 使用 TSQualifiedName 作为 namespace X.Y {} 的名称 (#16982)

    ¥Use TSQualifiedName for namespace X.Y {}'s name (#16982)

    namespace X.Y {} 不再表示为两个嵌套的 TSModuleDeclaration 节点,名称分别为 XY,而是表示为单个 TSModuleDeclaration,名称为 TSQualifiedName(X, Y)。此项变更使 AST 与 @typescript-eslint 解析器保持一致。

    ¥Rather than representing namespace X.Y {} as two nested TSModuleDeclaration nodes with names X and Y, it is now represented as a single TSModuleDeclaration whose name is a TSQualifiedName(X, Y). This change aligns the AST with the @typescript-eslint parser.

    // Example input
    namespace X.Y {}

    // AST in Babel 7
    {
    type: "TSModuleDeclaration",
    id: Identifier("X"),
    body: {
    type: "TSModuleDeclaration",
    id: Identifier("Y")
    body: TSModuleBlock([]),
    },
    }

    // AST in Babel 8
    {
    type: "TSModuleDeclaration",
    id: {
    type: "TSQualifiedName",
    left: Identifier("X"),
    right: Identifier("Y"),
    },
    body: TSModuleBlock([]),
    }

low

  • 除非启用 createParenthesizedExpression,否则不要生成 TSParenthesizedType#9546#12608)。

    ¥Don't generate TSParenthesizedType unless createParenthesizedExpression is enabled (#9546, #12608)

    input.ts
    type T = ({});

    // Babel 8 with createParenthesizedExpression: true, and Babel 7
    TSParenthesizedType { typeAnnotation: TSTypeLiteral { members: [] } }

    // Babel 8 with createParenthesizedExpression: false
    TSTypeLiteral { members: [] }

    迁移:如果你需要有关括号的信息,请指定 createParenthesizedExpression 解析器选项。

    ¥Migration: If you need information about parentheses, specify the createParenthesizedExpression parser option.

    babel.config.json
    { "parserOpts": { "createParenthesizedExpression": true } }

    createParenthesizedExpressionfalse 时,你还可以使用 node.extra.parenthesized 来检测 node 是否包含在括号中。

    ¥When createParenthesizedExpression is false, you can also use node.extra.parenthesized to detect whether node is wrapped in parentheses.

API 变更

¥API Changes

所有软件包

¥All packages

low

  • 禁止导入内部文件(#14013#14179)。

    ¥Disallow importing internal files (#14013, #14179).

    迁移:仅使用导出的 API。如果你依赖 Babel 内部组件,请提交问题并告知我们。

    ¥Migration: Use the exported API only. If you are relying on Babel internals, please open an issue and let us know.

@babel/core

medium

  • 禁止同步使用 babel.transformbabel.transformFilebabel.transformFromAstbabel.parsebabel.loadOptionsbabel.loadPartialConfigbabel.createConfigItem#11110#12695#15869)。

    ¥Disallow using babel.transform, babel.transformFile, babel.transformFromAst, babel.parse, babel.loadOptions, babel.loadPartialConfig and babel.createConfigItem synchronously (#11110, #12695, #15869).

    迁移:上述 API 需要回调参数。如果你不提供回调,请使用其同步版本:babel.transformSyncbabel.transformFileSyncbabel.transformFromAstSyncbabel.parseSyncbabel.loadOptionsSyncbabel.loadPartialConfigSyncbabel.createConfigItemSync

    ¥Migration: The APIs above require a callback argument. If you are not providing a callback, please use their sync versions: babel.transformSync, babel.transformFileSync, babel.transformFromAstSync, babel.parseSync, babel.loadOptionsSync, babel.loadPartialConfigSync and babel.createConfigItemSync.

@babel/generator

low

  • 移除 CodeGenerator 类 (#16126)

    ¥Remove CodeGenerator class (#16126)

    迁移:在 Babel 8 中,未记录的 CodeGenerator 类已被移除,请使用默认导出的 generate 函数。

    ¥Migration: In Babel 8 the undocumented CodeGenerator class has been removed, please use the default exported generate function instead.

    - new CodeGenerator(ast).generate()
    + generate(ast)

@babel/types

medium

  • 拒绝 t.identifier 构建器 (#10917) 中的无效标识符名称。

    ¥Reject invalid identifier names in t.identifier builder (#10917).

    babel-plugin.js
    // Empty string is an invalid identifier name
    t.identifier("");

    迁移:使用有效名称调用 t.identifier

    ¥Migration: Call t.identifier with a valid name.

  • 拒绝 t.variableDeclaration 构建器中的无效变量声明符(#10917#17217

    ¥Reject invalid variable declarator in t.variableDeclaration builder (#10917, #17217)

    babel-plugin.js
    // var [x] is invalid without an initializer
    t.variableDeclaration("var", [
    t.variableDeclarator(t.arrayPattern([t.identifier("x")]))
    ]);
  • Expression 别名中移除 Super (#14750)。

    ¥Remove Super from the Expression alias (#14750).

    Super 节点在父类调用 super() 和父类属性 super.foo 中代表 super。由于 super 不能是独立表达式,因此在 Babel 8 中,t.isExpression(t.super()) 将返回 false

    ¥A Super node represents super in super call super() and super property super.foo. As super can not be a standalone expression, t.isExpression(t.super()) will return false in Babel 8.

    迁移:t.isExpressiont.assertsExpression 函数以及 t.Expression 类型别名的搜索用法:如果他们还需要接受 Super 节点,请相应地更新它们。

    ¥Migration: Search usage of the t.isExpression and t.assertsExpression functions, and of the t.Expression type alias: if they need to also accept Super nodes, update them accordingly.

    my-babel-plugin.js
    // Add `.foo` to an expression
    - if (t.isExpression(path.node)) {
    + if (t.isExpression(path.node) || t.isSuper(path.node)) {
    path.replaceWith(
    t.memberExpression(
    path.node,
    t.identifier("foo")
    ))
    }

    如果不涉及 super()super.foo,则无需更新用法:

    ¥You don't have to update the usage if super() and super.foo is not involved:

    my-babel-plugin.js
    // define an expression as a computed key of `foo`
    if (t.isExpression(path.node)) {
    path.replaceWith(
    t.memberExpression(
    t.identifier("foo"),
    // `super` can not be a computed key, so we don't update `isExpression`
    path.node,
    /* computed */ true
    ))
    }
  • LVal 别名中移除 AssignmentPatternRestElement#17387

    ¥Remove AssignmentPattern and RestElement from the LVal alias (#17387)

    LVal 节点表示赋值表达式左侧 (LHS) 的有效节点。由于 AssignmentPatternRestElement 不能是 LHS,因此在 Babel 8 中,t.isLVal(t.assignmentPattern(...))t.isLVal(t.restElement(...)) 将返回 false

    ¥An LVal node represents valid nodes as the left hand side (LHS) of an assignment expression. As AssignmentPattern and RestElement can not be the LHS, t.isLVal(t.assignmentPattern(...)) and t.isLVal(t.restElement(...)) will return false in Babel 8.

    迁移:t.isLValt.assertsLVal 函数以及 t.LVal 类型别名的搜索用法:如果他们还需要接受 AssignmentPatternRestElement 节点,你可以使用 t.PatternLike 扩展 t.LVal

    ¥Migration: Search usage of the t.isLVal and t.assertsLVal functions, and of the t.LVal type alias: if they need to also accept AssignmentPattern or RestElement nodes, you can broaden t.LVal with t.PatternLike:

    my-babel-plugin.js
    // Iterate rest element within an object pattern
    for (const propertyPath of path.get("properties")) {
    - if (t.isLVal(propertyPath.node)) {
    + if (t.isLVal(propertyPath.node) || t.isPatternLike(propertyPath.node)) {
    doSomethingWith(propertyPath);
    }
    }
  • LVal 别名中移除 TSParameterProperty (#17391)

    ¥Remove TSParameterProperty from the LVal alias (#17391)

    LVal 节点表示赋值表达式左侧 (LHS) 的有效节点。TSParameterProperty 是一种特殊的函数参数类型,仅允许在类构造函数中使用。由于 TSParameterProperty 不能作为 LHS,因此在 Babel 8 中 t.isLVal(t.tsParameterProperty(...)) 将返回 false

    ¥An LVal node represents valid nodes as the left hand side (LHS) of an assignment expression. A TSParameterProperty is a special function parameter type allowed only in a class constructor. Since TSParameterProperty can not be the LHS, t.isLVal(t.tsParameterProperty(...)) will return false in Babel 8.

  • 要求 bigint 作为 t.bigIntLiteral#17378)的唯一参数

    ¥Require a bigint as the only argument of t.bigIntLiteral (#17378)

    这是由于相应的 AST 形状变更 造成的。

    ¥This is due to the corresponding AST shape change.

    迁移:将 bigint 原语传递给 bigIntLiteral 构建器。bigIntLiteral 构建器从 Babel 7.28 开始支持 bigint,你可以在升级到 Babel 8 之前开始迁移。

    ¥Migration: Pass the bigint primitive to the bigIntLiteral builder. Support of bigint in the bigIntLiteral builder starts from Babel 7.28, you can begin the migration before you upgrade to Babel 8

    my-babel-codemod.js
      t.bigIntLiteral(
  • "0xff020000000000000000000000000002"

  • 0xff02000000000000000000000000000002n )

- Require an `Identifier` node as the third argument of `t.tsTypeParameter` ([#12829](https://github.com/babel/babel/pull/12829))

This is due to the corresponding [AST shape change](#ast-TSTypeParameter).

__Migration__: Wrap the `name` string within the `identifier` builder

```diff title="my-babel-codemod.js"
t.tsTypeParameter(
/* constraint */ undefined,
/* default */ undefined,
+ t.identifier(
name
+ )
)
  • 要求 TSLiteralType 节点作为 t.tsImportType#17046)的第一个参数

    ¥Require a TSLiteralType node as the first argument of t.tsImportType (#17046)

    这是由于相应的 AST 形状变更 造成的。

    ¥This is due to the corresponding AST shape change.

    迁移:将 argument 字符串字面量封装在 tsLiteralType 构建器中

    ¥Migration: Wrap the argument string literal within the tsLiteralType builder

    my-babel-codemod.js
      t.tsImportType(
    + t.tsLiteralType(
    t.stringLiteral("foo")
    + )
    )
  • 要求 TSEnumBody 节点作为 t.tsEnumDeclaration#16979)的第二个参数

    ¥Require a TSEnumBody node as the second argument of t.tsEnumDeclaration (#16979)

    这是由于相应的 AST 形状变更 造成的。

    ¥This is due to the corresponding AST shape change.

    迁移:将 members 数组封装在 tsEnumBody 构建器中

    ¥Migration: Wrap the members array within the tsEnumBody builder

    my-babel-codemod.js
    // Create `enum ColorType { Red, Green, Blue }`
    t.tsEnumDeclaration(
    t.identifier("ColorType"),
    - [
    + t.tsEnumBody([
    t.tsEnumMember(t.identifier("Red")),
    t.tsEnumMember(t.identifier("Green")),
    t.tsEnumMember(t.identifier("Blue"))
    - ],
    + ]),
    )
  • 更新 t.tsMappedType 签名 (#16733)

    ¥Update the t.tsMappedType signature (#16733)

    这是由于相应的 AST 形状变更 造成的。

    ¥This is due to the corresponding AST shape change.

    // Babel 7
    declare function tsMappedType(
    typeParameter: TSTypeParameter,
    typeAnnotation?: TSType,
    nameType?: TSType
    ): TSMappedType

    // Babel 8
    declare function tsMappedType(
    key: Identifier,
    constraint: TSType,
    nameType?: TSType,
    typeAnnotation?: TSType
    ): TSMappedType

    迁移:参见以下示例。

    ¥Migration: See the example below.

    my-babel-codemod.ts
    // To create { [P in string as Q]: number }

    // Babel 7
    t.tsMappedType(
    t.tsTypeParameter(t.tsStringKeyword(), undefined, "P"),
    t.tsNumberKeyword(),
    t.tsTypeReference(t.identifier("Q"))
    )

    // Babel 8
    t.tsMappedType(
    t.identifier("P"),
    t.tsStringKeyword(),
    t.tsTypeReference(t.identifier("Q")),
    t.tsNumberKeyword()
    )
  • TSModuleDeclaration 的第二个参数 (body) 不能再是 TSModuleDeclaration (#16982)

    ¥The second argument (body) of TSModuleDeclaration cannot be a TSModuleDeclaration anymore (#16982)

  • t.tsModuleDeclaration 的第二个参数 (body) 不能再是 TSModuleDeclaration 节点 (#16982)

    ¥The second argument (body) of t.tsModuleDeclaration cannot be a TSModuleDeclaration node anymore (#16982)

    迁移:创建一个导出 TSModuleDeclarationTSModuleBlock 主体,或者创建一个以 TSQualifiedName 为名称的 TSModuleDeclaration

    ¥Migration: Either create a TSModuleBlock body that exports the TSModuleDeclaration, or create a single TSModuleDeclaration that has a TSQualifiedName as its name.

    my-babel-codemod.js
      // Option 1

    // Create `namespace X.Y {}`
    t.tsModuleDeclaration(
    t.identifier("X"),
    + t.exportNamedDeclaration(
    t.tsModuleDeclaration(
    t.identifier("Y"),
    t.tsModuleBlock([])
    ),
    + ),
    )

    ```diff title="my-babel-codemod.js"
    // Option 2

    // Create `namespace X.Y {}`
    t.tsModuleDeclaration(
    + t.tsQualifiedName(
    t.identifier("X"),
    - t.tsModuleDeclaration(
    t.identifier("Y"),
    + ),
    t.tsModuleBlock([])
    - )
    )

low

  • 移除 t.jSX*t.tS* 构建器别名(#6989#15527

    ¥Remove t.jSX* and t.tS* builder aliases (#6989, #15527)

    迁移:改用 t.jsx*t.ts*。例如,将 t.jSXIdentifier("foo") 替换为 t.jsxIdentifier("foo")

    ¥Migration: Use t.jsx* and t.ts* instead. For example, replace t.jSXIdentifier("foo") with t.jsxIdentifier("foo").

  • t.jsxElement 中移除 selfClosing 参数(#14464

    ¥Remove selfClosing argument from t.jsxElement (#14464)

    - t.jsxElement(openingElement, closingElement, children, selfClosing?: boolean)
    + t.jsxElement(openingElement, closingElement, children)

    迁移:构建器中已不再使用 selfClosing 参数。你可以安全地将其移除。

    ¥Migration: The selfClosing argument was already not used in the builder. You can safely remove it.

  • t.memberExpression 中移除 optional 参数(#13407

    ¥Remove optional argument from t.memberExpression (#13407)

    - t.memberExpression(object, property, computed, optional?: boolean)
    + t.memberExpression(object, property, computed)

    迁移:构建器中已不再使用 optional 参数。你可以安全地将其移除。

    ¥Migration: The optional argument was already not used in the builder. You can safely remove it.

  • 删除 Noop 节点类型 (#12361)

    ¥Remove the Noop node type (#12361)

    迁移:没有通用的迁移路径:你应该将其替换为 Noop 用作占位符的实际节点。如果你依赖 Noop 并且没有其他选择,请提交问题并解释你的用例。

    ¥Migration: There is no generic migration path: you should replace it with the actual node that Noop is being used as a placeholder for. If you are depending on Noop and have no alternative, please open an issue and explain your use case.

  • t.objectTypeAnnotation#14465)中,将节点 ObjectTypeAnnotation 中的 indexerscallPropertiesinternalSlots 初始化为空数组。

    ¥Initialize indexers, callProperties and internalSlots in the node ObjectTypeAnnotation as an empty array in t.objectTypeAnnotation (#14465)

    在 Babel 7 中,构建器 t.objectTypeAnnotation 将它们初始化为 null,这与 @babel/parser 解析 Flow 对象类型注释的方式不一致。在 Babel 8 中,新的默认值 [] 与解析器行为匹配。

    ¥In Babel 7 the builder t.objectTypeAnnotation initializes them as null, this is inconsistent with how @babel/parser will parse the Flow object type annotations. In Babel 8 the new default value [] matches the parser behaviour.

  • 拒绝 t.numericLiteral 中的负数和 NaN/无穷大数(#15802

    ¥Reject negative and NaN/infinite numbers from t.numericLiteral (#15802)

    babel-plugin.js
    // NumericLiterals must be non-negative finite numbers.
    t.numericLiteral(-1);

    迁移:要表示负数,请使用 t.unaryExpression("-", t.numericLiteral(1))。要表示 NaN 或无穷大,请使用 t.identifier("NaN")。要将通用数值(也可以是负数、NaN 或无穷大)转换为正确的 AST 节点,请使用 t.valueToNode(num)

    ¥Migration: To represent a negative number, use t.unaryExpression("-", t.numericLiteral(1)). To represent NaN or Infinity, use t.identifier("NaN"). To convert a generic numeric value (which could also be negative, NaN, or an inifinity) to the proper AST node, use t.valueToNode(num).

@babel/parser

除以下列出的更改外,@babel/parser 受所有 AST 变更 的影响。

¥Other than the changes listed below, @babel/parser is affected by all the AST changes.

low

  • 在 Flow 和 TypeScript 之间对齐 Babel 解析器错误代码 (#13294)

    ¥Align Babel parser error codes between Flow and TypeScript (#13294)

    OptionalBindingPatternerror.code 已重命名为 PatternIsOptional

    ¥The error.code for OptionalBindingPattern is renamed as PatternIsOptional.

  • 从选项 tokens: true 返回的 tokens[].type 中移除 updateContext 字段(#13768

    ¥Remove updateContext field from tokens[].type returned from option tokens: true (#13768)

    babel-integration.js
    import { parse } from "@babel/parser";

    const { tokens } = parse("a = 42", { tokens: true });
    tokens[0].type;
    // Babel 7
    // { label: "name", updateContext: null, ...other properties }
    // Babel 8
    // { label: "name", ... other properties }

    请注意,tokens[].type 是一个不透明对象,用作 token 类型的标识,就像一个符号一样。其确切结构应作为内部实现细节。

    ¥Note that tokens[].type is meant to be an opaque object used as an identity for token types, as if it was a symol. Its exact shape is meant to be an internal implementation detail.

  • 将私有名称 (#priv) 标记为单个 privateName 标记 (#13256)

    ¥Tokenize private names (#priv) as a single privateName token (#13256)

    babel-integration.js
    import { parse } from "@babel/parser";

    const { tokens } = parse("class C { #priv }", { tokens: true });
    tokens.filter(t => t.start >= 10 && t.end <= 15) // get tokens for `#priv`
    // Babel 7
    // [
    // Token (#) { value: "#", start: 10, end: 11 },
    // Token (name) { value: "priv", start: 11, end: 15 }
    // ]
    // Babel 8
    // [
    // Token (privateName) { value: "priv", start: 10, end: 15 }
    // ]
  • 将模板字面量标记为 templateNonTailtemplateTail (#13919)

    ¥Tokenize template literals as templateNonTail and templateTail (#13919)

    babel-integration.js
    import { parse } from "@babel/parser";

    const { tokens } = parse("`head${x}middle${y}tail`", { tokens: true });
    console.log(tokens); // print tokens
    // Babel 7
    // [
    // Token (`),
    // Token (template) { value: "head" }, Token (${),
    // Token (name) { value: "x" }, Token (}),
    // Token (template) { value: "middle" }, Token (${),
    // Token (name) { value: "y" }, Token (}),
    // Token (template) { value: "tail" }
    // Token (`)
    // ]
    // Babel 8
    // [
    // Token (templateNonTail) { value: "head" },
    // Token (name) { value: "x" },
    // Token (templateNonTail) { value: "middle" },
    // Token (name) { value: "y" },
    // Token (templateTail) { value: "tail" }
    // ]
  • ObjectProperty 节点中移除 extra.shorthand#16521

    ¥Remove extra.shorthand from ObjectProperty nodes (#16521)

    迁移:使用 node.shorthand 而不是 node.extra.shorthand

    ¥Migration: Use node.shorthand rather than node.extra.shorthand.

@babel/traverse

medium

  • NodePath (#16655) 中移除 isisnthasequals 方法

    ¥Remove is, isnt, has, equals methods from NodePath (#16655)

    迁移:改为直接比较 path.node 的属性。

    ¥Migration: Directly compare properties of path.node instead.

    - functionExpressionPath.equals("id", idNode)
    + functionExpressionPath.node.id === idNode

    - functionExpressionPath.is("id")
    - functionExpressionPath.has("id")
    + functionExpressionPath.node.id

    - functionExpressionPath.has("arguments")
    + !!functionExpressionPath.node.arguments.length

    - functionExpressionPath.isnt("async")
    + !functionExpressionPath.node.async
  • 移除 Scope.prototype.traverseScope#parentBlockScope#hub (#16705)

    ¥Remove Scope.prototype.traverse, Scope#parentBlock and Scope#hub (#16705)

    迁移:改用 scope.path 的方法和属性:

    ¥Migration: Use scope.path methods and properties instead:

    - scope.traverse(scopeRootNode, visitor, state)
    + scope.path.traverse(visitor, state)

    - scope.parentBlock
    + scope.path.parent

    - scope.hub
    + scope.path.hub
  • 移除 Scope.prototype.getAllBindingsOfKindScope.prototype.toArray#16705

    ¥Remove Scope.prototype.getAllBindingsOfKind and Scope.prototype.toArray (#16705)

    这些方法已被删除,因为它们在我们的代码库中不再使用。

    ¥These methods have been removed as they are not used anymore in our code base.

    迁移:你可以将它们从 Babel 7 的源代码复制粘贴到你的插件中。

    ¥Migration: You can copy&paste them from Babel 7's source to your plugin.

  • NodePath (#16655) 中移除 hoistupdateSiblingKeyscallsetScoperesyncpopContextpushContextsetupsetKey 方法

    ¥Remove hoist, updateSiblingKeys, call, setScope, resync, popContext, pushContext, setup, setKey methods from NodePath (#16655)

    这些方法应为私有方法,因此没有真正的迁移方法。如果你的插件/构建因此更改而无法正常工作,请随时打开一个问题并告诉我们你如何使用这些方法,我们将在 Babel 8 发布后看看可以做些什么。

    ¥These methods are meant to be private so there is no real migration approach. If your plugin / build is broken by this change, feel free to open an issue and tell us how you use these methods and we can see what we can do after Babel 8 is released.

low

  • Scope#rename 中移除 block 参数(#15288

    ¥Remove block argument from Scope#rename (#15288)

    - rename(oldName: string, newName?: string, block?: t.Pattern | t.Scopable)
    + rename(oldName: string, newName?: string)

    迁移:不要将其他块传递给 scope.rename(),而是直接在该块对应的作用域中调用 .rename()

    ¥Migration: Instead of passing a different block to scope.rename(), directly call .rename() on the scope corresponding to that block.

  • Scope#uidsScope#references 替换为 Scope#uidsSetScope#referencesSet#16624

    ¥Replace Scope#uids and Scope#references with Scope#uidsSet and Scope#referencesSet (#16624)

    它们已从布尔值对象更改为 Set 对象。此外,它们现在仅在程序作用域 (scope.getProgramParent()) 上定义,而不是在所有作用域对象上定义。

    ¥They have been changed from objects with boolean values to Set objects. In addition to that, they are now only defined on the program scope (scope.getProgramParent()) rather than on all scope objects.

    - if (programScope.references["foo"])
    + if (programScope.referencesSet.has("foo"))
  • 允许将跳过的 NodePath 重新排队 (#13291)

    ¥Allow skipped NodePaths to be requeued (#13291)

    NodePath#requeue() 可以重新排队跳过的 NodePath。这实际上是一个错误修复,但它会导致 Babel 7 中 @babel/plugin-transform-block-scoping暂时死区 实现出现无限循环:它也可能会破坏其他插件。

    ¥NodePath#requeue() can requeue a skipped NodePath. This is actually a bugfix, but it causes an infinite loop in the temporal dead zone implementation of @babel/plugin-transform-block-scoping in Babel 7: it may break other plugins as well.

    迁移:如果你想保留旧的行为,可以在调用 NodePath#requeue() 之前使用 NodePath#shouldSkip 检查 NodePath 是否被跳过。

    ¥Migration: If you want to preserve the old behavior, you can use NodePath#shouldSkip to check whether a NodePath has been skipped before calling NodePath#requeue().

  • ScopeNodePath (#16504#16705) 中移除以 _ 开头的方法

    ¥Remove methods starting with _ from Scope and NodePath (#16504, #16705)

    // NodePath.prototype
    _assertUnremoved
    _call
    _callRemovalHooks
    _containerInsert
    _containerInsertAfter
    _containerInsertBefore
    _getKey
    _getPattern
    _getQueueContexts
    _getTypeAnnotation
    _markRemoved
    _remove
    _removeFromScope
    _replaceWith
    _resolve
    _resyncKey
    _resyncList
    _resyncParent
    _resyncRemoved
    _verifyNodeList

    // Scope.prototype
    _renameFromMap
    _generateUid

    这些方法应为私有方法,因此没有真正的迁移方法。如果你的插件/构建因此更改而无法正常工作,请随时打开一个问题并告诉我们你如何使用这些方法,我们将在 Babel 8 发布后看看可以做些什么。

    ¥These methods are meant to be private so there is no real migration approach. If your plugin / build is broken by this change, feel free to open an issue and tell us how you use these methods and we can see what we can do after Babel 8 is released.

@babel/eslint-plugin

low

  • 删除 exports 对象的 default 属性 (#14180)

    ¥Remove the default property of the exports object (#14180)

    迁移:如果你在 ESLint 配置中使用该插件,则此项变更无效。但是,如果你要扩展 @babel/eslint-plugin,请确保从 require("@babel/eslint-plugin") 而不是 require("@babel/eslint-plugin").default 获取导出。

    ¥Migration: This change has no effect if you are using the plugin in your ESLint config. However, if you are extending @babel/eslint-plugin, ensure that you obtain exports from require("@babel/eslint-plugin") rather than require("@babel/eslint-plugin").default.

    my-eslint-plugin.cjs
    // Don't add `.default` after `require()`
    const { rules, rulesConfig } = require("@babel/eslint-plugin")

@babel/compat-data

  • plugins.json#14976)中的第 4 阶段插件条目从 proposal-* 重命名为 transform-*

    ¥Rename stage 4 plugin entries from proposal-* to transform-* in plugins.json (#14976)

    此项变更还会影响 @babel/helper-compilation-targetsisRequired 函数,该函数接收插件名称作为其第一个参数。

    ¥This change also affects the isRequired function of @babel/helper-compilation-targets, which receives plugin names as its first parameter.

    迁移:例如,使用 transform-class-properties 而不是 proposal-class-properties。有关重命名插件的完整列表,请参阅 Babel 8 迁移的软件包重命名部分

    ¥Migration: For example, use transform-class-properties rather than proposal-class-properties. For a complete list of renamed plugin, see Packages Renames section of Babel 8 migration.

    my-babel-plugin.js
    module.exports = api => {
    const targets = api.targets();
    // The targets have native optional chaining support
    // if `transform-optional-chaining` is _not_ required
    const optionalChainingSupported = !isRequired(
    - "proposal-optional-chaining",
    + "transform-optional-chaining",
    targets
    );
    };
  • 直接将数据导出为 JSON 文件(#17267)。

    ¥Directly export data as JSON files (#17267)

    软件包的入口点现在是 JSON 文件,而不是 JS 文件。

    ¥The entrypoints of the package are now JSON files, rather than JS files.

    迁移:如果你从 ESM 导入此包,则需要更改导入,并在其中添加 with { type: "json" }

    ¥Migration: If you are importing this package from ESM, you will need to change your imports adding with { type: "json" } to them.

low

  • data/native-modules.json 中移除 ios_saf#15068

    ¥Remove ios_saf from data/native-modules.json (#15068)

    迁移:请改用 ios

    ¥Migration: Use ios instead.

@babel/helper-replace-supers

low

  • 移除命名导出 environmentVisitor (#15550)

    ¥Remove named export environmentVisitor (#15550)

    迁移:从 @babel/helper-environment-visitor 导入。

    ¥Migration: Import it from @babel/helper-environment-visitor.

    - import { environmentVisitor } from "@babel/helper-replace-supers";
    + import environmentVisitor from `@babel/helper-environment-visitor`;
  • 移除命名导出 skipAllButComputedKey (#15550)

    ¥Remove named export skipAllButComputedKey (#15550)

    迁移:请改用 requeueComputedKeyAndDecorators。查找并替换以下导入和用法。

    ¥Migration: Use requeueComputedKeyAndDecorators instead. Find and replace the following import and usage

    my-babel7-plugin.js
    import { skipAllButComputedKey } from "@babel/helper-replace-supers";
    skipAllButComputedKey(path);

    to

    my-babel8-plugin.js
    import { requeueComputedKeyAndDecorators } from `@babel/helper-environment-visitor`;
    path.skip();
    requeueComputedKeyAndDecorators(path);

@babel/helper-simple-access

low

  • 从默认导出 (#15550) 中删除第三个参数 includeUpdateExpression

    ¥Remove the the third parameter includeUpdateExpression from the default export (#15550)

    请注意,Babel 8 的行为与默认的 Babel 7 行为(即 includeUpdateExpression: true)相同。

    ¥Note that the Babel 8 behavior is the same as the default Babel 7 behavior (i.e. includeUpdateExpression: true).

@babel/highlight

low

插件 API 变更

¥Plugin API changes

medium

  • 从插件传递中移除 getModuleName#12724

    ¥Remove getModuleName from plugin pass (#12724)

    迁移:请改用 .file.getModuleName

    ¥Migration: Use .file.getModuleName instead.

    my-babel-plugin.js
    module.exports = {
    name: "my-babel-plugin",
    visitor: {
    Identifier(path, pass) {
    - const moduleName = pass.getModuleName();
    + const moduleName = pass.file.getModuleName();
    }
    }
    }

low

  • 从插件传递中移除 addImport#15576

    ¥Remove addImport from plugin pass (#15576)

    此更改可能不会影响你的插件,因为此方法在 Babel 7 中已经引发错误。

    ¥This change probably will not affect your plugin as this method is already throwing an error in Babel 7.

    迁移:改用 @babel/helper-module-imports 中的 addNamedaddDefault

    ¥Migration: Use addNamed or addDefault from @babel/helper-module-imports instead.

  • 停止支持将插件字段作为命名导出 (#15576)

    ¥Stop supporting plugin fields as named exports (#15576)

    例如,以下文件不再是有效的插件:

    ¥For example, the following file is not a valid plugin anymore:

    legacy-babel-plugin.js
    export const name = "legacy-babel-plugin";
    export const visitor = {
    Identifier() {}
    }

    迁移:找到此类模式并使用默认导出,例如导出插件对象或工厂函数。

    ¥Migration: Find such patterns and use a default export instead, either exporting a plugin object or a factory function.

    my-babel-plugin.cjs
    export default {
    name: "babel-plugin",
    visitor: {
    Identifier() {}
    }
    }