最基础的javascript重点知识,我的理解就是把一个方法,一个声明变量等代码,拆解成一棵树,我们进入方法就是访问(visitor)这棵树,每个属性就是树的节点,既然知道如何用AST访问这棵树,那么相应的也可以用来修改这棵树,比如修改方法名,变量名啥的,例如可用recast来实现一个源码修改工具
实战:实现简单的babel插件:修改变量名, 把所有变量名为a的变成b
1、新建文件夹,babel-plugin-import,建一个test.js文件做测试,node_modeles文件夹下再建一个babel-plugin-import,里面放一个index,js和package.json文件
步骤:
a、首先我们要找到定义变量的地方,然后判断变量名是不是a,如果是就把它换成b
b、找到定义变量的语句,节点类型是VariableDeclarator,
c、VariableDeclarator 的id.name属性就是变量名
2、登陆ast语法树在线生成网站esprima.org/demo/parse.…
var a =45 生成的语法树:
{ "type": "Program", "body": [ { "type": "VariableDeclaration", "declarations": [ { "type": "VariableDeclarator", "id": { "type": "Identifier", "name": "a" }, "init": { "type": "Literal", "value": 45, "raw": "45" } } ], "kind": "var" } ], "sourceType": "script" }
3、 index.js文件:module.exports=({types})=>({
VariableDeclarator(path,state){
var { node, parent} = path;
var { id,type,start,end ,init} = node;
if(id.name == 'a'){
// ast语法树想改变某个值,就是用对应的ast来换。所以要构建b的Identifier
path.node.id = types.identifier('b'); // 用 "path.node.id" 而不能直接用解构的"id"
}
},
})
4、test.js文件测试:
var code1 ="var a = 45";
console.log(transformcode(code1));
function transformcode(code){
var ast = babel.transform(code,{
plugins:["import"] // 使用自己编写的 babel-plugin-import插件
}).ast;
//transformFromAst AST转码
return babel.transformFromAst(ast,null,{babelrc:true,extends:path.resolve(__dirname,'./.babelrc')}).code;
}
执行 node test.js ,输出 var b = 45,执行成功~
5、其他:@babel/core 是babel的核心包 Babel.transform(code, options,function(){ Result }); Transform 函数可以传入code,返回转换后的代码
所以写插件的思路:1、确认修改的节点类型,2、找到修改的节点属性,3、根据旧的ast构建新的ast并替换
构建ast 结合babel type和 AST explorer