Babel 是什么
Babel 是一个 JavaScript 编译器
编译的定义就是从一种编程语言转成另一种编程语言。主要指的是高级语言到低级语言。一般编译器 Compiler 是指高级语言到低级语言的转换工具,对于高级语言到高级语言的转换工具,被叫做转换编译器,简称转译器 (Transpiler)。
所以Babel在工程化当中是用来语法转换,转换成低端环境的浏览器或者node环境也能够执行的代码,一开始是ES6转化到ES5,所以一开始也叫6to5,不过后来也跟进最新的标准,甚至可以转换到更低级的规范标准,也就更名到babel了
我们最常见的babel插件 就是
- @babel/preset-env
- @babel/preset-react
Babel的具体用途
- 转译语法,比如es6、7、8、next,或者typescript等
- 用作静态编译分析,比如混淆,api文档等
- 自制语法糖转换
Babel的工作流程
babel本身是一个微内核的架构,即采用插件的形式工作,所以又叫做插件化架构,指的是软件的内核相对较小,主要功能和业务逻辑都通过插件实现。插件化架构一般有两个核心的概念:内核和插件,我们前端一直在用的浏览器也可以称为插件化架构,页面是插件,通过挂载的window提供API,这些就不细说了,而babel的内核即编译流程总共分为三个阶段:解析(parse),转换(transform),生成(generate):
- parse:源码进行词法分析和语法分析转成抽象语法树(AST)
- transform:遍历 AST,调用各种 transform 插件对 AST 进行增删改
- generate:把转换后的 AST 生成目标代码
在每个阶段都会调用各自的插件,插件的形式又分为preset和plugins,这也是插件机制里很常见的,运行机制是
- Plugin 会运行在 Preset 之前。
- Plugin 会从前到后顺序执行。
- Preset 的顺序从后向前
Babel的AST
Babel的解析是一个叫babylon的parser库,babylon基于acorn,并且对 AST 节点和属性都做了扩展,其实eslint的parser也是基于acorn拓展的,acorn本身也是插件形式拓展的,所以很多工具的parser都用acorn进行拓展,感兴趣的同学也可以搜一下这份历史
在线可以用https://astexplorer.net/ 查看自己的代码的ast
比如以下:
const author = "cnyballk"

Babel 的插件是如何工作的
Babel 在完成 AST 编译后,会调用插件对 AST 做修改,插件调用分为了四个阶段:
- 遍历插件集合,执行插件的 pre 方法。
- 遍历插件集合,合并插件的 visitor 方法 ,输出是一个包含了所有插件逻辑的 visitor 方法。
- 执行第二步合成的 visitor 方法。
- 遍历插件集合,执行插件的 post 方法。
很显然,我们能看到visitor 其实是合并的,这是babel为了性能而做出的选择,如果在写插件的时候需要对语法进行分析,需要在语法转换之前进行,否则可能会与@babel/preset-env等插件集的visitor 混合,以至于分析错误。
@babel/preset-env
上面介绍了工作流程以及插件的工作机制,但是平时不开发插件也不必关注,后面介绍一下常见的插件@babel/preset-env
@babel/preset-env是一个智能预设,可让您使用最新的JavaScript,而无需微观管理目标环境所需的语法转换(以及可选的浏览器polyfill)。这都使您的生活更轻松,JavaScript包更小!
env是一个插件集,首先插件集是什么?大家可以想一想语法这么多plugin,一个个install再进行配置也要很多时间,而且大家也记不住这么多,这样就会导致使用成本升高。这时候可以封装成一个 preset,可以通过 preset 来批量引入 plugin 并进行一些配置。preset 就是对 babel 配置的一层封装
再通过暴露配置 进行精准配置,比如targets
{"targets": "> 0.25%, not dead"}
或者对象,用来描述支持的最低版本的浏览器
{"targets": {"chrome": "59",}}
更详尽的options可以查看https://www.babeljs.cn/docs/babel-preset-env#options
最后
Babel 从2013年至今更新了已经到了7的版本了,核心都是为了更好的将语法转换, 并且降低用户的使用成本和插件的开发成本,我们在学习的时候也需要围绕核心来学习,我们后续也可以试着用babel开发一个插件出来更好的认识Babel
参考资料
https://babeljs.io/docs/en/
https://github.com/jamiebuilds/babel-handbook/blob/master/translations/en/plugin-handbook.md
