前言
现在对 ast(abstract syntax tree 虚拟语法树)应该也不陌生了。像 vue react 开发所写的非浏览器标准的代码,最后都是转化成符合标准的代码,都是中间靠这个处理。也包括小程序,react-native 这些也是要经过同样处理转换。
ast 三板斧:parse(解析)-> transform(转换)-> generate(生成)。
听起来有点像变形金刚,我在想法术里的变身是不是原理也是这样:实体拆散成原子,原子转换变形,然后再重新组合。哈哈。
ast 工具其实很多,babel 应该是前端接触较多较早的一个,毕竟很长一段时间内都是它在帮着处理前端的编译。babel 对于上面三板斧拆成了三个工具:@babel/parser,@babel/traverse,@babel/generator。
乍看之下,其它两个都对得上,好像 transform 不太对。其实转换规则是自己定的,babel 也不知道使用者要转成啥,所以它提供了一个 traverse 工具,用来方便获取节点。因为 ast 是一串层级深又复杂的对象,很难自己手动找到想要的节点,所以提供了一个遍历工具。
当然有个遍历工具还是不够,最好还是搭配一个很牛网站:https://www.astexplorer.net 可以直接左边输入源代码,右边看结构树。从这个网站里可以看到其实还有很多别的 ast 工具,每个工具都有自己的节点定义。
实践
现在尝试进行一段代码的转换:
// input:
import Input from './Input';
export const Component = (props) => <div><Input onChange={props.onChange} /></div>;
// output:
import { Input } from './Input';
const map = {
run: () => {}
};
export default function Component(props) {
return <div><Input onChange={map[props.method]} /></div>;
}
就是,1、把 import default 导出变成解构导出,2、把 export 分散导出变成 default 导出,3、把事件的触发函数变成调用一个事件映射的属性。