必须:
@babel/core,下面全部是@babel/core的dependency,所以安装@babel/core就可以了 使用包:
- @babel/parser -转换code为ast tree
- @babel/traverse -遍历ast tree
- @babel/generate -生成新的code
- @babel/core
- types 必须使用,构造新的节点,判断ast节点类型;
- transformSync 整合parser,traverse,generate的方法,直接使用可不用自己分步调用
- @babel/helper-plugin-utils 帮助声明plugins的帮助方法,可选;
通用思路
code -> ast -> transformed ast -> transformed code
- 代码到ast:parser
- 对ast进行处理:traverse
- 将ast生成code:generate
如何写一个babel插件的前提
- 知道input是什么,input的ast是什么
- 知道output是什么,output的ast是什么
- 思考从input到output是什么 和写一个函数相似,知道输入输出后,在内部进行语法树操作,得到想要的ast,再将ast转成code即可;(此part一般babel都帮忙做了)
babel转化的方法
transformSync
常用的babel 构建AST Tree的方法
转换必然包含构建新的树,需要合理利用api,来看最终目的节点里面转换出来是什么类型的,选择该类型的节点构造起,节点构造太多,只有在实践中积累;
- memberExpression(object, property): obj.name
- callExpression(callee, arguments): func(x) 被调用者 + 参数
- identifier(name); a,定义一个变量
- binaryExpression(operator, left, right); a + b 这种
- assignmentExpression(operator, left, right); 分配操作
- variableDeclaration(kind, declaration); // 声明变量
t.assignmentExpression(
"=",
t.identifier('x'),
t.identifier(10),
);
// x = 10
包括她自身的判断方法isXXX,具体可以在网站查看
代码层面
这里是plugin实例
普通-step-by-step
// 高级版,使用babel-core提供的功能babel.transformSync
const babel = require('@babel/core');
const code = 'const x = 10';
const result = babel.transformSync(code, {
// 默认是false,指定是true才会生成
ast: true,
plugins: [
function myTransformPlugin() {
return {
visitor: {
Identifier(path) {
console.log(path);
if (path.isIdentifier({ name: 'x'})) {
path.node.name = 'n';
}
}
}
}
}
]
});
console.log(result, result.code);
优化-使用transformSync
const babel = require('@babel/core');
// source
const code = `
function hello(name) {
return 'hello' + name;
}
console.log(hello('shelly'));
`;
// traget:
// function olleh(eman) {
// return 'h' + 'e' + 'l' + 'l' + 'o' + eman;
// }
// console.log(olleh('shelly'));
function myCustomeplugin() {
return {
// traversal 阶段,深度优先遍历搜索语法树,visit ast的每个节点
// 可以对每种类型的节点,来visit; 比如Identifier,StringLiteral
visitor: {
Identifier(path) {
console.log(path, 'path', path.node.name, path.parentPath.isMemberExpression() );
if (!path.parentPath.isMemberExpression()) {
path.node.name = path.node.name.split('').reverse().join('');
}
},
StringLiteral(path) {
console.log('stringliteral', path.node);
const newNode = path.node.value
.split('')
.map((c) => babel.types.stringLiteral(c))
.reduce((total, cur) => babel.types.binaryExpression('+', total, cur));
path.replaceWith(newNode);
// 添加了新下级,如果往下遍历,会无限循环
path.skip();
}
}
}
}
const result = babel.transformSync(code, {
plugins: [myCustomeplugin]
});
console.log(result, result.code);
必用网站
babel-types参考手册builder+validator
ast树生成探索,看到转换后的
babel-core node api
参考:# Step-by-step guide for writing a custom babel transformation