什么是AST?为什么存在?
https://en.wikipedia.org/wiki/Abstract_syntax_tree(维基解释,需翻墙)
大致意思是为了方便编译js脚本,用来表达抽象的语法结构而存在的。。。它不表达语法中的每一个细节,只为了表达结构
什么是Babel?干嘛用的?
Babel官网:https://www.babeljs.cn/docs/
简单来说就是为了做语法转换而存在的,就是将后来出现的更加优秀的语言或者框架,转变为可兼容运行的语言,这里包含且不止js
安装Babel
cnpm install --save-dev babel-loader babel-core babel-preset-env babel-plugin-transform-runtime babel-plugin-istanbul babel-polyfill babel-preset-stage-2 babel-register
Babel工作流程
Parse ==> transform ==>Generate
所以要想完成这几个步骤,babel 提供了几个实用工具(Babylon,babel-traverse,babel-generator)
实战问题:如何取出js中引入文件的路径?
例:(路径都是瞎写的!!)
import axios from './123/axios'
import b from '/a'
function square(n) {
return n * n;
}
这里要取出from后面的文件路径。
先来看一下将这段代码转为AST后是什么:
两个import对象,一个函数对象(最上面的是require函数产生的对象,可忽略),我没有展开树结构,详细的结构可以拷贝上面的代码到这里查看
提取路径代码:
首先生成文件config.ts,内容如上代码,然后去先解析文件,输出ATS,从json中找到文件名。。。
var fs = require('fs');
let babel = require('babel-core');
let t = require('babel-types');
let template = require('@babel/template');
let traverse = require('babel-traverse')
let babylon =require("babylon") ;
// 读取需要修改的源代码内容
var content = fs.readFileSync('./config.ts').toString();
let paramName;
//访问数据的选项
let visitor = {
//输出导入文件参数
ImportDeclaration(path) {
console.log(path.node.source.value);
},
//修改函数参数
FunctionDeclaration(path){
// console.log( path.node.params[0]);
const param = path.node.params[0];
paramName = param.name;
param.name = "x";
},
Identifier(path) {
if (path.node.name === paramName) {
path.node.name = "x";
}
}
}
// 通过 plugin 转换源代码 parse 出来的AST 抽象语法树,并且返回结果
let result= babel.transform(content, {
plugins: [
{ visitor}
]
});
console.warn(`res: ${result.code}`);
// 把新代码写入新文件.
// fs.writeFileSync('newRoute.ts', result.code);
使用node执行后输出结果:
./123/axios
/a
res: import axios from './123/axios';
import b from '/a';
function square(x) {
return x * x;
}
前两行为问题输出结果,后面的打印是修改函数参数后的输出结果,将函数原来的参数 'x' 转变为'n'
对于没看过babel资料的读者来说,以上代码需要解释的有以下几点:
-
transform是什么? 还记得上面babel工作的步骤吗?这里一步到位,直接转化过来,返回的是一个对象,包含(code,map,ast)你可以打印输出以下,ast输出为obj
-
visitor是干嘛的? 这里的visitor是作为访问数据的接口存在的,第一步你打印出的是个对象,你必须通过visitor才能访问到对象内部
-
visitor里面的函数命名可以随意吗? 不可以!!!!这里面的函数类似css的选择器,是为了选择匹配的参数,这里不多解释,需要补这方面的知识可以去查看babel手册(很全面)
-
函数中的path是干嘛用的? 表示两个节点间的连接对象,你可以认为是找到匹配对象入口
传送门:
如何往文件中填加新的数据:https://www.jianshu.com/p/3c495dcbed49
Babel手册(上下):https://github.com/jamiebuilds/babel-handbook/blob/master/translations/zh-Hans/README.md
Babel的transform的参数有哪些:https://www.babeljs.cn/docs/options
查看AST的树结构和json:https://astexplorer.net/