源码版本选择
目前的babel功能已经非常丰富了,源码读起来比较困难,因此选择babel早期的版本进行探索。本文选取的版本为tag v1.7.7的版本。在这个版本时,babel还不叫babel,而是叫做6to5,就是将ES6转成ES5。
源码运行
在这个版本中,有一个bin目录,其中就包含一个可执行文件6to5,可以直接在命令行中输入bin/6to5 -o output.js input.js,就可以测试6to5的功能,其中input.js为输入文件,-o output.js代表将输出内容写到output.js文件中。
以箭头函数为例
const a = (m, n) => m + n;
a(1,2);
输出结果为
(function() {
var a = function(m, n) {
return m + n;
};
a(1,2);
})();
可以看到6to5将箭头函数转换成了普通函数的形式,并且在最外层包了一层立即执行函数。
调试准备工作
为了方便调试源码,本文使用vscode,并且设置launch.json如下。其中skipFiles为调试时跳过的文件,在这里跳过node_modules文件夹下的文件。
{
"version": "0.2.0",
"configurations": [
{
"type": "pwa-node",
"request": "launch",
"name": "debug Program",
"skipFiles": ["${workspaceFolder}/node_modules/**"],
"runtimeExecutable": "node",
"args": ["./bin/6to5", "-o", "output.js", "input.js"]
}
]
}
源码分析
源码运行顺序
在6to5文件中,引入了util文件。
util文件主要提供了一些函数,在文件的最后是导出语法转换模版,如果提供了templates.json,就直接将该文件的内容作为模版,否则使用6to5中的template目录下定义好的模版。在221行的地方,调用了parse函数来得到模版内容的抽象语法树,并调用removeProperties函数来移除部分对于代码转换无用的属性。
接下来就是调用transform.js文件中的transform函数,在该函数中,调用了parse函数获取抽象语法树,然后调用traverse函数,可以更改抽象语法树中的节点,最后调用generate函数生成ES5的代码。
断点设置
由于在引入util文件时,就会利用parse和traverse等重要函数来批量生成模版,为了跳过模版的生成过程,直接在调用transform函数处打断点。
想看transform的具体操作的话,找到transformers目录下对应的文件,打断点。如箭头函数的转换,在6to5中就是将箭头函数的函数体放在ReturnStatement中,并在外层包上BlockStatement,如果有this的话,还要对this进行转换。