Skip to main content

@babel/parser

Babel解析器(以前叫Babylon)是一个用于 Babel的JavaScript解析器。

  • 默认启用最新的 ECMAScript 版本(ES2020)。
  • 注释附件。
  • 支持 JSX、Flow 和 TypeScript。
  • 支持实验性语言提案(接受任何至少达到 stage-0 的 PR)。

致谢​

🌐 Credits

严重依赖于 acorn 和 acorn-jsx,感谢 @RReverser 和 @marijnh 的出色工作。

🌐 Heavily based on acorn and acorn-jsx, thanks to the awesome work of @RReverser and @marijnh.

应用接口​

🌐 API

babelParser.parse(code, [options])​

babelParser.parseExpression(code, [options])​

parse() 会把提供的 code 解析为整个 ECMAScript 程序,而 parseExpression() 则尝试解析单个表达式,注重性能。有疑问的话,就用 .parse()。

选项​

🌐 Options

历史
版本变更
v8.0.0添加了 locations
v7.28.0添加了 sourceType: "commonjs"
v7.27.0添加了 allowYieldOutsideFunction
v7.26.0添加了 startIndex
v7.23.0添加了 createImportExpressions
v7.21.0添加了 allowNewTargetOutsideFunction 和 annexB
v7.16.0添加了 startColumn
v7.15.0添加了 attachComment
v7.7.0添加了 errorRecovery
v7.5.0添加了 allowUndeclaredExports
v7.2.0添加了 createParenthesizedExpressions
  • allowImportExportEverywhere:默认情况下,import 和 export 声明只能出现在程序的顶层。将此选项设置为 true 可以让它们出现在允许语句的任何地方。

  • allowAwaitOutsideFunction:默认情况下,await 只能在异步函数内部使用,或者当启用了 topLevelAwait 插件时,才能在模块的顶层作用域中使用。将此设置为 true 可以在脚本的顶层作用域中也使用它。不过更推荐使用 topLevelAwait 插件。

  • allowYieldOutsideFunction:默认情况下,yield 只能在生成器函数内部使用。将其设置为 true,也可以在顶层使用。

  • allowNewTargetOutsideFunction:默认情况下,new.target 不允许在函数或类之外使用。将其设置为 true 可以接受这样的代码。

  • allowReturnOutsideFunction:默认情况下,在顶层使用 return 语句会报错。将其设置为 true 可以允许这种代码。

  • allowSuperOutsideMethod:默认情况下,不允许在类和对象方法之外使用 super。将其设置为 true 可以允许这样的代码。

  • allowUndeclaredExports:默认情况下,导出在当前模块作用域中未声明的标识符会引发错误。虽然这种行为是 ECMAScript 模块规范要求的,但 Babel 的解析器无法预测插件管道后续可能插入适当声明的转换,因此有时将此选项设置为 true 很重要,以防解析器过早地抱怨稍后会添加的未声明导出。

  • attachComment:默认情况下,Babel 会将注释附加到相邻的 AST 节点。当这个选项设置为 false 时,注释不会被附加。当输入代码中有很多注释时,这可以提高最多 30% 的性能。@babel/eslint-parser 会帮你设置好它。不建议在 Babel 转换中使用 attachComment: false,因为这样会移除输出代码中的所有注释,并且会导致像 /* istanbul ignore next */ 这样的注解失效。

  • 附录B:默认情况下,Babel 会根据 ECMAScript 的附录 B “面向浏览器的额外 ECMAScript 特性” 语法解析 JavaScript。当该选项设置为 false 时,Babel 将解析不带附录 B 特定扩展的语法。

  • createImportExpressions:默认情况下,解析器会将动态导入 import() 解析为调用表达式节点。当此选项设置为 true 时,会改为创建 ImportExpression AST 节点。此选项在 Babel 8 中默认将设为 true。

  • createParenthesizedExpressions:默认情况下,解析器会在表达式节点上设置 extra.parenthesized。当此选项设置为 true 时,则会创建 ParenthesizedExpression AST 节点。

  • errorRecovery:默认情况下,当 Babel 发现一些无效代码时,总是会抛出错误。当此选项设置为 true 时,它会存储解析错误并尝试继续解析无效的输入文件。生成的 AST 将有一个 errors 属性,表示所有解析错误的数组。请注意,即使启用了此选项,@babel/parser 仍可能因不可恢复的错误而抛出。

  • locations:布尔值。true 是默认值,会给每个节点添加一个 loc 属性,该属性是一个对象,包含 start 和 end 属性,这些属性又是包含 line 和 column 数字的对象。当设置为 false 时,输出的 AST 中将不包含 loc 属性。

  • 插件:包含你想要启用的插件的数组。

  • sourceType:指明代码应以哪种模式进行解析。可以是 "script"、"commonjs"、"module" 或 "unambiguous" 之一。默认是 "script"。"unambiguous" 会让 @babel/parser 尝试根据是否存在 ES6 import 或 export 语句来进行_猜测_。包含 ES6 import 和 export 的文件会被视为 "module",否则为 "script"。

    "commonjs" 模式表示代码应该在像 Node.js 这样的 CommonJS 环境中运行。它与 "script" 模式大体兼容,只是允许在顶层使用 return、new.target 和 using/await using 声明。

  • sourceFilename:将输出的 AST 节点与它们的源文件名关联。当从多个输入文件的 AST 生成代码和源码映射时非常有用。

  • startColumn:默认情况下,解析的代码会被当作从第1行,第0列开始。你也可以提供一个列号来从指定列开始。这在与其他源代码工具集成时很有用。

  • startLine: 默认情况下,解析的代码会被当作从第1行,第0列开始。你也可以提供一个行号来从指定行开始。这在与其他源代码工具集成时很有用。

  • startIndex:默认情况下,所有源索引从 0 开始。使用此选项,你可以提供一个替代的起始索引。当 startLine 大于 1 时,为了确保 AST 源索引的准确性,应该始终提供此选项。对与其他源工具的整合很有用。

  • strictMode:默认情况下,ECMAScript 代码只有在存在 "use strict"; 指令或解析的文件是 ECMAScript 模块时才会作为严格模式解析。将此选项设置为 true 可以始终以严格模式解析文件。

  • ranges:为每个节点添加一个 range 属性:[node.start, node.end]

  • tokens:将所有解析的 tokens 添加到 File 节点上的 tokens 属性

输出​

🌐 Output

Babel 解析器根据 Babel AST 格式 生成 AST。它基于 ESTree 规范,但有以下偏差:

🌐 The Babel parser generates AST according to Babel AST format. It is based on ESTree spec with the following deviations:

note

estree 插件可以恢复这些偏差。只有在你将 Babel AST 传给其他符合 ESTree 的工具时才使用它。

JSX 代码的 AST 基于 Facebook JSX 抽象语法树。

🌐 AST for JSX code is based on Facebook JSX AST.

服务器​

🌐 Semver

Babel 解析器在大多数情况下遵循语义化版本规范。唯一需要注意的是,某些符合规范的 bug 修复可能会在补丁版本中发布。

🌐 The Babel Parser follows semver in most situations. The only thing to note is that some spec-compliancy bug fixes may be released under patch versions.

举个例子:我们会对类似 #107 的早期错误推送修复——每个文件有多个默认导出。即使这会导致构建失败,这也会被视为一个错误修复。

🌐 For example: We push a fix to early error on something like #107 - multiple default exports per file. That would be considered a bug fix even though it would cause a build to fail.

示例​

🌐 Example

JavaScript
require("@babel/parser").parse("code", {
// parse in strict mode and allow module declarations
sourceType: "module",

plugins: [
// enable jsx and flow syntax
"jsx",
"flow",
],
});

插件​

🌐 Plugins

各种各样的​

🌐 Miscellaneous

名称代码示例
estree (仓库)不适用

语言扩展​

🌐 Language extensions

历史
版本变更
v7.6.0添加了 v8intrinsic
名称代码示例
flow (仓库)var a: string = "";
flowComments (文档)/*:: type Foo = {...}; */
jsx (仓库)<a attr="b">{s}</a>
typescript (仓库)var a: string = "";
v8intrinsic%DebugPrint(foo);

ECMAScript 提案(链接)​

🌐 ECMAScript proposals

NameCode Example
asyncDoExpressions (proposal)async do { await requestAPI().json() }
decorators (proposal)
decorators-legacy
@a class A {}
decoratorAutoAccessors (proposal)class Example { @reactive accessor myBool = false; }
deferredImportEvaluation (proposal)import defer * as ns from "dep";
destructuringPrivate (proposal)class Example { #x = 1; method() { const { #x: x } = this; } }
discardBinding (proposal)using void = new Lock(mutex)
doExpressions (proposal)var a = do { if (true) { 'hi'; } };
exportDefaultFrom (proposal)export v from "mod"
functionBind (proposal)a::b, ::console.log
functionSent (proposal)function* g() { function.sent }
moduleBlocks (proposal)let m = module { export let y = 1; };
optionalChainingAssign (proposal)x?.prop = 2
partialApplication (proposal)f(?, a)
pipelineOperator (proposal)a |> b
sourcePhaseImports (proposal)import source x from "./x"
throwExpressions (proposal)() => throw new Error("")

插件选项​

🌐 Plugins options

历史
版本更改
7.21.0decorators 的 decoratorsBeforeExport 选项默认行为是允许装饰器出现在 export 关键字的前面或后面。
7.19.0recordAndTuple 插件的 syntaxType 选项默认值为 hash;为 decorators 插件添加了 allowCallParenthesized 选项。
7.17.0为 hack 管道操作符的 topicToken 选项添加了 @@ 和 ^^
7.16.0为 typescript 插件添加了 disallowAmbiguousJSXLike。为 hack 管道操作符的 topicToken 选项添加了 ^
7.14.0为 typescript 插件添加了 dts
note

当一个插件被多次指定时,只考虑第一个选项。

  • decorators:

    • allowCallParenthesized (boolean,默认为true)

      当 false 时,禁止在 @(...)() 形式中使用装饰器,改用 @(...())。阶段 3 的装饰器提案使用 allowCallParenthesized: false。

    • decoratorsBeforeExport(boolean)

      默认情况下,导出类上的装饰器可以放在 export 关键字的前面或后面。当设置了这个选项后,装饰器将只能放在指定的位置。

      JavaScript
      // decoratorsBeforeExport: true
      @dec
      export class C {}

      // decoratorsBeforeExport: false
      export
      @dec
      class C {}
      caution

      此选项已被弃用,并将在未来版本中移除。当明确将此选项设置为 true 或 false 时有效的代码,即使未设置此选项也同样有效。

  • optionalChainingAssign:

    • version(必填,接受值:2023-07) 这个提案目前还处于第一阶段,因此很可能会受到重大变动的影响。 你必须指定你使用的提案版本,以确保 Babel 能够继续以兼容的方式解析你的代码。
  • pipelineOperator:

    • proposal(必填,接受的值:fsharp、hack) 对于管道操作符有几种不同的提案。 这个选项用于选择使用哪一个提案。 更多信息请参见 plugin-proposal-pipeline-operator,其中包括一个比较它们行为的表格。
    • topicToken(当 proposal 为 hack 时必填,可接受的值:%、#、^、@@、^^) hack 提案在它的管道中使用了一个“主题”占位符。 对于这个主题占位符,有两种不同的选择。 这个选项就是选择用哪个标记来指代主题。
  • partialApplication:

    • version(必填,唯一有效值为 2018-07)。指定你正在使用的部分应用提案的版本。2018-07 表示该提案在 2018 年 7 月的 TC39 会议上提出时的样子。
  • flow:

    • all(boolean,默认:false) 有些代码在 Flow 和普通 JavaScript 中的含义不同。例如,foo<T>(x) 在 Flow 中被解析为带类型参数的调用表达式,但根据 ECMAScript 规范,它会被解析为比较操作(foo < T > x)。默认情况下,babel-parser 只有在文件以 // @flow 指令开头时才会将这些模糊的结构解析为 Flow 类型。 将此选项设置为 true,可以始终将文件解析为好像指定了 // @flow。
  • typescript

    • dts(boolean,默认 false) 这个选项会启用在 TypeScript 环境上下文中的解析,在这里某些语法规则会有所不同(比如 .d.ts 文件和 declare module 块内部)。更多关于环境上下文的信息,请参考 TypeScript Handbook 和 TypeScript Deep Dive。
    • disallowAmbiguousJSXLike(boolean,默认为 false) 即使没有启用 jsx 插件,这个选项也会禁止使用可能与 JSX 混淆的语法(<X> y 类型断言和 <X>() => {} 类型参数)。它在解析 .mts 和 .mjs 文件时的行为与 tsc 相同。

错误代码​

🌐 Error codes

历史
版本变更
v7.14.0添加了错误代码

错误代码对于处理 @babel/parser 抛出的错误很有用。

🌐 Error codes are useful for handling the errors thrown by @babel/parser.

有两个错误代码,code 和 reasonCode。

🌐 There are two error codes, code and reasonCode.

  • code
    • 错误的大致分类(例如 BABEL_PARSER_SYNTAX_ERROR、BABEL_PARSER_SOURCETYPE_MODULE_REQUIRED)。
  • reasonCode
    • 错误的详细分类(例如 MissingSemicolon、VarRedeclaration)。

使用 errorRecovery 错误代码的示例:

🌐 Example of using error codes with errorRecovery:

JavaScript
const { parse } = require("@babel/parser");

const ast = parse(`a b`, { errorRecovery: true });

console.log(ast.errors[0].code); // BABEL_PARSER_SYNTAX_ERROR
console.log(ast.errors[0].reasonCode); // MissingSemicolon

常见问题​

🌐 FAQ

Babel 解析器会支持插件系统吗?​

🌐 Will the Babel parser support a plugin system?

之前的问题: #1351, #6694.

🌐 Previous issues: #1351, #6694.

我们目前不打算承诺支持插件的 API 或由此产生的生态系统(维护 Babel 自己的插件系统已经有够多的工作了)。如何让那个 API 有效还不清楚,而且这会限制我们重构和优化代码库的能力。

🌐 We currently aren't willing to commit to supporting the API for plugins or the resulting ecosystem (there is already enough work maintaining Babel's own plugin system). It's not clear how to make that API effective, and it would limit our ability to refactor and optimize the codebase.

对于那些想要创建自己的自定义语法的用户,我们目前的建议是让用户复刻解析器。

🌐 Our current recommendation for those that want to create their own custom syntax is for users to fork the parser.

要使用你自定义的解析器,你可以在你的 options 中添加一个插件,通过它的 npm 包名调用解析器,或者如果使用 JavaScript,则通过 require 调用它,

🌐 To consume your custom parser, you can add a plugin to your options to call the parser via its npm package name or require it if using JavaScript,

JavaScript
const parse = require("custom-fork-of-babel-parser-on-npm-here");

module.exports = {
plugins: [
{
parserOverride(code, opts) {
return parse(code, opts);
},
},
],
};