跳到主内容

Babel 插件手册 - API篇

· 8分钟阅读

Babel 实际上是一组模块的集合。本节我们将探索一些主要的模块,解释它们是做什么的以及如何使用它们。

注意:本节内容不是详细的 API 文档的替代品,正式的 API 文档将很快提供出来。

Babylon 是 Babel 的解析器。最初是 从 Acorn 项目 fork 出来的。Acorn 非常快,易于使用,并且针对非标准特性(以及那些未来的标准特性) 设计了一个基于插件的架构。

首先,让我们安装它。

$ npm install --save babylon

babylon

Babylon 是 Babel 的解析器。最初是 从 Acorn 项目 fork 出来的。Acorn 非常快,易于使用,并且针对非标准特性(以及那些未来的标准特性) 设计了一个基于插件的架构。

首先,让我们安装它。

$ npm install --save babylon

先从解析一个代码字符串开始:

import * as babylon from "babylon";

const code = `function square(n) {
return n * n;
}`;

babylon.parse(code);
// Node {
// type: "File",
// start: 0,
// end: 38,
// loc: SourceLocation {...},
// program: Node {...},
// comments: [],
// tokens: [...]
// }

我们还能像下面这样传递选项给 parse()方法:

babylon.parse(code, {
sourceType: "module", // default: "script"
plugins: ["jsx"], // default: []
});

sourceType 可以是 "module" 或者 "script",它表示 Babylon 应该用哪种模式来解析。 "module" 将会在严格模式下解析并且允许模块定义,"script" 则不会。

注意: sourceType 的默认值是 "script" 并且在发现 importexport 时产生错误。 使用 scourceType: "module" 来避免这些错误。

由于 Babylon 使用了基于插件的架构,因此有一个 plugins 选项可以开关内置的插件。 注意 Babylon 尚未对外部插件开放此 API 接口,不排除未来会开放此 API。

要查看完整的插件列表,请参见 Babylon README文件。.

babel-traverse

Babel Traverse(遍历)模块维护了整棵树的状态,并且负责替换、移除和添加节点。

运行以下命令安装:

$ npm install --save babel-traverse

我们可以和 Babylon 一起使用来遍历和更新节点:

import * as babylon from "babylon";
import traverse from "babel-traverse";

const code = `function square(n) {
return n * n;
}`;

const ast = babylon.parse(code);

traverse(ast, {
enter(path) {
if (path.node.type === "Identifier" && path.node.name === "n") {
path.node.name = "x";
}
},
});

babel-types

Babel Types 模块是一个用于 AST 节点的 Lodash 式工具库(译注:Lodash 是一个 JavaScript 函数工具库,提供了基于函数式编程风格的众多工具函数), 它包含了构造、验证以及变换 AST 节点的方法。 该工具库包含考虑周到的工具方法,对编写处理 AST 逻辑非常有用。

可以运行以下命令来安装它:

$ npm install --save babel-types

然后按如下所示来使用:

import traverse from "babel-traverse";
import * as t from "babel-types";

traverse(ast, {
enter(path) {
if (t.isIdentifier(path.node, { name: "n" })) {
path.node.name = "x";
}
},
});

Definitions(定义)

Babel Types 模块拥有每一个单一类型节点的定义,包括节点包含哪些属性,什么是合法值,如何构建节点、遍历节点,以及节点的别名等信息。

单一节点类型的定义形式如下:

defineType("BinaryExpression", {
builder: ["operator", "left", "right"],
fields: {
operator: {
validate: assertValueType("string"),
},
left: {
validate: assertNodeType("Expression"),
},
right: {
validate: assertNodeType("Expression"),
},
},
visitor: ["left", "right"],
aliases: ["Binary", "Expression"],
});

Builders(构建器)

你会注意到上面的 BinaryExpression 定义有一个 builder 字段。.

builder: ["operator", "left", "right"];

这是由于每一个节点类型都有构造器方法 builder,按类似下面的方式使用:

t.binaryExpression("*", t.identifier("a"), t.identifier("b"));

可以创建如下所示的 AST:

{
type: "BinaryExpression",
operator: "*",
left: {
type: "Identifier",
name: "a"
},
right: {
type: "Identifier",
name: "b"
}
}

当打印出来之后是这样的:

a * b;

构造器还会验证自身创建的节点,并在错误使用的情形下会抛出描述性错误,这就引出了下一个方法类型。

Validators(验证器)

BinaryExpression 的定义还包含了节点的字段 fields 信息,以及如何验证这些字段。

fields: {
operator: {
validate: assertValueType("string")
},
left: {
validate: assertNodeType("Expression")
},
right: {
validate: assertNodeType("Expression")
}
}

可以创建两种验证方法。第一种是 isX。.

t.isBinaryExpression(maybeBinaryExpressionNode);

这个测试用来确保节点是一个二进制表达式,另外你也可以传入第二个参数来确保节点包含特定的属性和值。

t.isBinaryExpression(maybeBinaryExpressionNode, { operator: "*" });

这些方法还有一种断言式的版本,会抛出异常而不是返回 truefalse。.

t.assertBinaryExpression(maybeBinaryExpressionNode);
t.assertBinaryExpression(maybeBinaryExpressionNode, { operator: "*" });
// Error: Expected type "BinaryExpression" with option { "operator": "*" }

babel-generator

Babel Generator 模块是 Babel 的代码生成器,它读取 AST 并将其转换为代码和源码映射(sourcemaps)。

运行以下命令来安装它:

$ npm install --save babel-generator

然后按如下方式使用:

import * as babylon from "babylon";
import generate from "babel-generator";

const code = `function square(n) {
return n * n;
}`;

const ast = babylon.parse(code);

generate(ast, {}, code);
// {
// code: "...",
// map: "..."
// }

你也可以给 generate() 方法传递选项。.

generate(
ast,
{
retainLines: false,
compact: "auto",
concise: false,
quotes: "double",
// ...
},
code
);

babel-template

babel-template 是另一个虽然很小但却非常有用的模块。 它能让你编写字符串形式且带有占位符的代码来代替手动编码, 尤其是生成的大规模 AST 的时候。 在计算机科学中,这种能力被称为准引用(quasiquotes)。

$ npm install --save babel-template
import template from "babel-template";
import generate from "babel-generator";
import * as t from "babel-types";

const buildRequire = template(`
var IMPORT_NAME = require(SOURCE);
`);

const ast = buildRequire({
IMPORT_NAME: t.identifier("myModule"),
SOURCE: t.stringLiteral("my-module"),
});

console.log(generate(ast).code);
var myModule = require("my-module");