Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

babel初学者的一些常见误区 #68

Open
youngwind opened this issue Apr 24, 2016 · 2 comments
Open

babel初学者的一些常见误区 #68

youngwind opened this issue Apr 24, 2016 · 2 comments
Labels

Comments

@youngwind
Copy link
Owner

youngwind commented Apr 24, 2016

问题

使用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的处理有两个方法。

  1. 通过plugins插件,比如transform-object-assign解决object.assign
  2. 通过统一的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,如图所示
2016-04-24 11 33 39
不仅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。

参考资料:

  1. babel中如何使用stage-X
  2. 现在的各个stage都包含哪些新特性呢?
  3. es标准化的流程是什么样子?

开发环境与生产环境

babel是可以区分开发环境和生产环境的,就像webpack那样,具体可以参考这里

最后,这里有个很不错的babel中文手册,可供参考。

遗留问题

  1. 为了更深入得理解babel,计划自己写一个简单的babel插件。
  2. 把项目中常用的plugins抽象成preset(如果有必要的话)
  3. 寻找只引用需要的polyfill的解决方案,或许是时候研究rollup了。
@youngwind youngwind changed the title babel使用的一些误区 babel初学者的一些常见误区 Apr 24, 2016
@youngwind youngwind added the JS label Sep 29, 2016
@mqliao
Copy link

mqliao commented Mar 16, 2017

polyfill 确实太大了,对移动端web是个挑战

@Thinking80s
Copy link

那么配置的.babelrc文件中同时设置集合和插件也是一种兼容方式吧?{"presets": ["es2015", "stage-3"], "plugins": ["transform-runtime"]}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants