babel初学者的一些常见误区
youngwind opened this issue · 2 comments
问题
使用babel有一段时间了,但是一直没有仔细研究。上回在前端使用async解决回调的时候出现问题,后来引入了babel-polyfill才解决,其实那时候不太懂为什么一定要这么搞。今天趁着有时间再次通读了一边babel官网的文档,觉得很多问题比原先想得明白了。
babel5 VS babel6
babel是一个转换器,或者准确的说,babel5是一个转换器,babel6是一个容纳其他转换插件的容器。因为从babel6开始babel本身就不完成任何转换功能,所有功能都插件化了,意味着你除了安装babel6以外,还需要安装其他插件才能干活。
语法与api
我以前一直以为装了babel之后所有es6的语法都可以使用了,但是后来才发现不是。因为es6作为新的标准,它的拓展包括语法和api。
什么是语法呢?比如箭头函数
// before
() => {}
// after
function(){}
babel会将这些语法转换成es5的格式,从而让es6的语法可以运行。
但是,对于es6拓展的api可不是单纯通过转换语法就可以实现的
比如说,
//before
() => {
var demo = {
name:"youngwind"
}
Object.assign({},demo,{age:24})
}
//after
function () {
var demo = {
name:"youngwind"
}
Object.assign({},demo,{age:24})
}
看,babel虽然把箭头函数转换了,但是还是得执行Object.assign,可是es5中没有这个方法啊,所以即便是转换之后的代码在es5的环境下执行还是会报错。如果我们脱离babel来观察这个问题的话,你就会发现,这不就是ployfill嘛!整个ployfill就好啦!是的,这就是babel的第二部分功能:polyfill
babel对于这些兼容性api的处理有两个方法。
- 通过plugins插件,比如transform-object-assign解决object.assign
- 通过统一的polyfill,也就是babel-polyfill
关于babel-polyfill
babel-polyfill本质上也只是一个polyfill,官方文档中提到,它包括一个定制的regenerator runtime(用于解决generator和yield的问题)和zloirock开发的core.js (一个用于解决es6、es7 polyfill的大集合)。所以这也解释了为什么之前在前端使用async的时候需要引入polyfill了,见 #62 。换句话说,如果你不喜欢babel-polyfill的话,你也可以使用其他polyfill来代替它,完全不用考虑babel的感受:-D。而且babel-polyfill的体积也不小(压缩后90多k呢),之后其实可以考虑一下只引入需要用到的polyfill。
关于preset与plugin
前面已经提到,babel是靠一系列plugins起作用的,但是如果每回都需要配置一大堆插件的话,那样显得太麻烦了,所以在plugin之上有一个preset的概念,其实preset也就是特定插件的集合。比如我们常用的es2015 preset,它就包含下面这些plugins,如图所示
不仅preset之间也可以相互包含,你也可以很方便的自定义自己的preset,比如把公司项目常用的plugin集合弄到一个preset中,具体可以参考这儿
关于stage-X
一开始我也不知道为什么有些时候要使用stage-0啊,stage-1啊这些东西,后来搞明白了。这个还得从es这门语言的规范制定说起。es作为一门语音,它的规范制定是由某个委员会来统筹的。就像法律一样,一个标准的诞生是要经过很多次的讨论的:一开始是一些不成熟的想法(stage-0:Strawman),通过之后变成提议(stage-1:Proposal),再通过进入草案(stage-2: Draft),再通过进入候选(stage-3: Candidate),最后才能进入标准(stage-4:finished)。标准里面的每一条都得经过层层的筛选,并不是所有都能在最后进入标准的,所以使用stage-x里面的新特性是有一定风险的,比如我们用得很多的async和await,它就是属于stage3,还差一点就进入标准了。所以,如果你想使用还没有进入标准的一些新特性,你就需要包含相应的stage-x-preset或者plugins。
参考资料:
开发环境与生产环境
babel是可以区分开发环境和生产环境的,就像webpack那样,具体可以参考这里。
最后,这里有个很不错的babel中文手册,可供参考。
遗留问题
- 为了更深入得理解babel,计划自己写一个简单的babel插件。
- 把项目中常用的plugins抽象成preset(如果有必要的话)
- 寻找只引用需要的polyfill的解决方案,或许是时候研究rollup了。
polyfill 确实太大了,对移动端web是个挑战
那么配置的.babelrc文件中同时设置集合和插件也是一种兼容方式吧?{"presets": ["es2015", "stage-3"], "plugins": ["transform-runtime"]}