我们前端开发对于babel应该都是非常熟悉的,当然了,也有可能现时下会有一些不熟悉的人,随着互联网的发展,很多人用到的都是架构组或者进部门以前已经撸好的框架,脚手架肯定也都是完善的,那么有一部分人如果刚入行就直接空中楼阁去做业务的话,那还真有可能链bable都不太了解
本来是在梳理loader的时候把babel-loader的配置一笔带过了,但是我后来发现,可能有人不知道babel的原理,所以还是梳理一下,算是查漏补缺
1.什么是babel
babel本质上就是编译器,或者通俗点讲就叫翻译软件,能力就是把浏览器识别不了的代码翻译成浏览器可以识别的代码,但是这里的翻译是翻译两个不同版本的js规范而已,我们在webpack中常用方式就是babel-loader,然后这个loader使用默认配置也好,自己配置的.babelrc文件也好,都是可以的, .babelrc文件需要的配置项主要有预设(presets)和插件(plugins)
这里插播一下,其实有babel主要还是因为js语法标准每年的新标,从2015年的新标准一出,类似于class,let,for…of promise这样的新语法和API直接就让我们真香现场了,我们为了去使用这些新东西,又为了兼容浏览器,我们只能去写好再通过babel去转换了,不管是直接下载babel-cli还好还是用loader也好,当然了我们最常用的还是loader,因为我们大部分情况不会单独使用babel,所以我们这个babel的能力在开发的过程中是不可或缺的,虽然我们有时候会自动忽略,但是还是了解一下比较好
2.babel的能力
- Parse(解析):将源代码转换成更加抽象的表示方法(例如抽象语法树)
- Transform(转换):对(抽象语法树)做一些特殊处理,让它符合编译器的期望
- Generate(代码生成):将第二步经过转换过的(抽象语法树)生成新的代码
- 解析
将代码解析生成抽象语法树( 即AST ),也就是计算机理解我们代码的方式(扩展:一般来说每个 js 引擎都有自己的 AST,比如熟知的 v8,chrome 浏览器会把 js 源码转换为抽象语法树,再进一步转换为字节码或机器代码),而 babel 则是通过 babylon 实现的 。简单来说就是一个对于 JS 代码的一个编译过程,进行了词法分析与语法分析的过程。 - 转换
简单来讲就是通过解析生成的一个语法树,AST会分析是否属于符合规范的语法,如果不属于就会被删除或者被替换,直到所有的语法树中的都是符合规范的 - 代码生成
这个也简单,就是反向解析,怎么过来的怎么回去,重新转换为代码,只不过已经换成了新的,符合规范的代码
3.babel的使用
{
"plugins": [
"transform-remove-strict-mode",
["transform-nej-module", {"mode": "web"}]
],
"presets": [
[
'@babel/preset-env',
{
'target':{
"browser":["ie>=8","chrome>=62"],
"node":"8.9.0",
"safari":"tp"
},
"modules":false,
"debug":true,
"uglify":true
"useBuiltIns":true
}
]
]
}
- .babelrc内的代码是这样的,就是一个简单的配置,不用有逻辑,babel会自动引用这个文件且读取里边的配置
- env:env 的核心目的是通过配置得知目标环境的特点,然后只做必要的转换。例如目标浏览器支持 es2015,那么 es2015 这个 preset 其实是不需要的,于是代码就可以小一点(一般转化后的代码总是更长),构建时间也可以缩短一些。如果不写任何配置项,env 等价于 latest,也等价于 es2015 + es2016 + es2017 三个相加(不包含 stage-x 中的插件)。
- plugins:要加载和使用的插件,一些方法是presets中不提供的,这时候就需要单独引入了
常见插件的介绍:
transform-runtime
option参数:
helpers: boolean,默认true
使用babel的helper函数。
polyfill: boolean,默认true
使用babel的polyfill,但是不能完全取代babel-polyfill。
regenerator: boolean,默认true
使用babel的regenerator。
moduleName: string,默认babel-runtime
使用对应module处理。
{
"plugins": ["transform-runtime", options]
}
- transform-remove-console
这个没有配置参数直接使用即可,编译后的代码都会移除console,这个其实不在这里配置也可以
- presets:要加载和使用的preset ,每个 preset 表示一个预设插件列表,preset名前的babel-preset-可省略;presets列表的preset按从尾到头的逆序运行(为了兼容用户使用习惯)
- 同时设置了presets和plugins,那么plugins的先运行,因为两个参数都是数组,所以肯定是可以传递多个参数的,例如presets就可以传递react预设,然后传递env,注意,这里也是倒序,env写最上边,每个preset和plugin都可以再配置自己的option
3.执行顺序
- 执行 plugins 中所有的插件
- plugins 的插件,按照顺序依赖编译
- 所有 plugins 的插件执行完成,在执行 presets 预设
- presets 预设,按照倒序的顺序执行。(从最后一个执行)
- 完成编译
上边的代码我们可以看到一些配置,例如在presets中添加浏览器占市场份额的百分比多少的要添加兼容,比如版本号大于多少的要做兼容转换,都可以在其中配置,babel只是简单的说一下,以防连不可忽略的新规范的代码的转换的原理都不清楚