背景
现在前端编写代码都是每次编写,多处运行。但我们在写代码的过程中都是一处编写,百处填坑。或者依赖了大量插件,插件升级、老代码随之打算重构,都需要下很大力度去执行。我们一般都是去硬执行但随之带来了很多问题。比如AST的局限性、AST的复杂性
简介
全网最简单易上手,可读性最强的 AST 处理工具!它主要有以下特点
- 大幅减少代码量——如果你需要使用AST对代码进行升级、改造、分析,快用gogoAST帮你摆脱繁琐冗余的的代码,专注于你的核心逻辑。不需要traverse,像剥洋葱一样一层一层的对比、操作、构造ast节点。
- 降低理解成本——甚至不需要理解什么是CallExpression、Identifier、ImportDeclaration这些概念,就可以畅快运用AST。
- 基于recast,转换后的代码基本与源代码的格式差异最小。
- 凡是需要借助babel、recast、jscodeshift、esprima...完成的需求,gogoast都能帮你更快更简单的完成。
API
- 创建实例
const GG = require('gogoast');
const AST = GG.createAstObj(p, options);
- 通过选择器查找AST节点:getAstsBySelector
const { nodePathList, matchWildCardList } = AST.getAstsBySelector([
'$_$.setTip($_$, $_$)',
'tip.show($_$)'
]);
- 选择器是一段包含通配符(_)的代码
- nodePathList:返回找到的ast节点路径,包含自己节点、父节点等信息
- matchWildCardList:返回通配符_代表的节点信息,其中structure是节点完整信息,value是简略信息
- 通过选择器替换另一个选择器查找到的AST节点:replaceSelBySel
AST.replaceSelBySel('const $_$ = require($_$)', 'import $_$ from $_$');
AST.replaceSelBySel('$.extend(true, $_$, $_$)', 'Object.assign($_$, $_$)');
AST.replaceSelBySel('$.each($_$, function($_$, $_$) { $_$ } )', '$_$.forEach($_$, $_$)');
- 创建一个AST节点:buildAstByAstStr
const type = 'error';
const content = ASTNODE; // 从其他代码中提取出来或者自己构造的ast节点
GG.buildAstByAstStr(`
Alert.show({
type: '${type}',
content: '$_$content$_$'
})
`, {
content
})
- GG模块其他基本方法
- 将AST节点转成字符串 generate(ast)
- 获取AST节点的所有父节点 getParentListByAst(path)
- 判断一个AST节点是否包含某子节点,子节点用选择器表示 hasChildrenSelector(path, childSelector)
- 用一个AST节点替换某个字符串 replaceStrByAst
- replaceAstByAst
- getPrevAst
- getNextAst
- insertAstListBefore
- insertAstListAfter
- removeAst
- 特殊类型AST节点的构造方法
- buildObjectProperty
AST.buildObjectProperty({
url: 'getList',
type: 'get'
})
- appendJsxAttr
const locaid = '98s8dh3';
const params = [ 'a=${aa}', 'b=${{aaa:"222",xxx:{ssss:111}}}', 'c=${"s"}', 'd=${a+1}','e=${ ss?2:1}' ]
AST.appendJsxAttr({
'attr1: `{${'`'}gostr='$'{gostr};locaid=d${locaid};${params.join('&')}}${'`'}}`, // 模板字符串
a: `{a+1}`, // 表达式
b: `'a'`, // 字符串
c: `{a}` // 变量
});
// 结果:
<div attr1={`gostr=${gostr};locaid=d98s8dh3;a=${aa}&b=${{aaa:"222",xxx{ssss:111}}}&c=${"s"}&d=${a+1}&e=${ ss?2:1}}`}a={a+1} b='a' c={a}>
</div>
试例
js代码
import a from 'a';
console.log('get A')
var b = console.log()
console.log.bind()
var c = console.log
console.log = func
使用gogocode实现
const AST = GG.createAstObj(code);
AST.replaceSelBySel(`var $_$ = console.log()`, `$_$ = void 0`);
AST.replaceSelBySel(`console.log()`, null);
AST.replaceSelBySel(`var $_$ = console.log`, `$_$ = function(){}`);
const result = AST.generate();
相比自定义babel插件简化三分之一的代码,代码结构上也让人更好理解。