什么是Babel
相信很多新手没有听说过Babel
和ES6
,如果你是老手的话,那么请自动忽略~
ES6
ES6
也就是ECMAScript 6
,也就是最新的一代js规范,添加了很多语言的特性,包括模块管理,类,块级作用域等等内容。我最喜欢的就是箭头函数,优雅~
Babel
然而虽然ES6
很棒,但是现在几乎没有浏览器或者Node(我记得5.0已经全部支持了es6,可是为啥我试着却不行。。。似乎要开启全部的harmony)能够完全支持es6的代码,那么问题来了,如果我想体验一下es6的代码,怎么办??
一个很简单的思路便是:
我写个程序,将es6代码转换成es5代码进行运行不就好了,很棒
而Babel
就是干的这个事情。
babel5 和 babel6 的区别
对于Babel
来说,现在有了两个版本,一个是5,一个是6,那么两者有什么区别呢?
- 5对新手更加友好,因为只需要安装一个
babel
就可以了,而6需要安装比较多的东西和插件才可以。 - 相比5来说,6将命令行工具和API分开来了,最直观的感觉就是,当你想在代码中运行es6代码的话,需要安装
babel-core
,而如果你想在终端编译es6或者是运行es6版本的REPL的话,需要安装babel-cli
- 也许有人问,原先的
babel
去哪了?是这样的,这个babel
的package到了6版本之后虽然还是能安装,但是已经不具有任何的有效的代码了。取而代之的是一段提示文字,提示你需要安装babel-core
或者babel-cli
。所以你在babel6的情况下,完全不需要安装babel
- 6将babel插件化,当你第一次安装
babel-core
并且按照以前的方式来加载require hook的话,你回发现代码无法运行:require('babel-core/register');
就是因为babel6整体插件化了,如果你想使用es6语法,需要手动加载相关插件。
这里有一篇文章,建议看一下《The Six Things You Need To Know About Babel 6》
Quick Start
建立空文件夹 babel6
建立空文件夹babel6作为本次的目录,并npm init
安装Babel6
npm install babel-core --save
如果觉得慢,可以使用淘宝镜像cnpm
。
此时,基础的babel6就安装完成了,如果你想安装babel5,那么执行如下的代码
npm install babel@5 --save
即可使用babel5,那么在后文的中,统一使用babel6
require hook
安装好之后,问题来了,如何使用呢?
相信使用过coffee
的人一定知道register
,那么在babel中同样不例外,也可以使用同样的方法。
require('babel-core/register');
require('./app');
大家可能以为这样我就可以在app.js
中优雅的使用es6了,在babel5中确实是这样的,但是在babel6中,缺不一样了。
如果你这样写完,并没有任何作用,因为你缺少一个插件。
安装插件
如果想使用es6
语法,必须安装一个插件
npm install babel-preset-es2015
然后在文件夹下面创建一个叫.babelrc
的文件,并写入如下代码:
{
"presets": ["es2015"]
}
下面你就可以很优雅的书写你的es6代码了。
书写优雅的ES6代码
下面我们写一段优雅的代码
let first = (size, ...args) => [...args].slice(0, size);
export default first;
console.log(first(2,1,2,3));
Run it
直接运行,不说话~~~
内容解释
.babelrc
什么是.babelrc
文件呢?熟悉linux的同学一定知道,rc结尾的文件通常代表运行时自动加载的文件,配置等等的,类似bashrc,zshrc。同样babelrc在这里也是有同样的作用的,而且在babel6中,这个文件必不可少。
- 里面可以对babel命令进行配置,以后在使用babel的cli的时候,可以少写一些配置
- 还有一个
env
字段,可以对BABEL_ENV
或者NODE_ENV
指定的不同的环境变量,进行不同的编译操作
“presets”
这个是babel6新加的,就是代表需要启动什么样的预设转码,在babel6中,预设了6种,分别是
- es2015
- stage-0
- stage-1
- stage-2
- stage-3
- react
至于如何安装,请查看balel官网
而且,对.babelrc
的设置,你可以存放在package.json中的。如下:
{
...
"babel": {
"presets": ["es2015"]
},
...
}
require hook
require hook 的作用就是替换原先的require,以便在加载自动对代码进行编译,运行。
其实这个做的便是重写require.extensions
中对应的扩展名的加载程序,并且默认会判断这个文件是否是node_modules
中的模块,如果是的话,那么将不会进行转换。否则的话,会进行转换。
CLI
其实babel也可以当做全局变量来使用的
npm install babel-cli -g
安装上后,会安装如下四个程序到全局环境中:
- babel
- babel-node
- babel-doctor
- babel-external-helpers
babel
这个就是编译js文件的全局变量,具体如何使用,大家请参照官网。使用方法和coffee,style,less了类似,就不多讲了
babel-node
这里主要说一下这个东西,就是这个的作用就是提供一个node
命令相同的REPL环境,不过这个环境会在执行之前讲代码进行编译。
坑1:上文讲到,babel6默认是无法编译es6文件的,需要你手动安装
es2015
的preset,同样,全局模式下,也需要这个preset。
那么问题来了,我们怎么安装这个preset呢?global?所以这是一个坑,我在babel的issue中找到这样的一条。作者给出这样的回答:我们处理preset和plugin是依据于输入的文件,而你直接运行CLI是没有输入文件的,也就无法定位preset和plugin的位置。言下之意就是不要全局安装,虽然我们给你了你全局安装的方式。然后作者关闭了issue,表示很无奈。。。。
所以,如果大家想体验一下es6的REPL的话,建议安装babel5
npm install babel@5 -g
babel-doctor
就是检查babel状况的, 主要检查以下几个内容
- 是否发现了
.babelrc
配置文件 - 是否有重复的babel安装包,比如说安装了5和6
- 所有的babel安装包是否已经升级到了最新版
- 并且 npm >= 3.3.0
babel-external-helpers
就是讲一些公共的帮助函数提取成一个文件,其实就做了这一个作用。。。
总结
这是我的第一篇关于es6的教程,如果大家有什么不好的地方,请及时想我反馈。 Blog
更新
2015-11-15 添加了CLI一节
loose 模式貌似还一直有问题
赞,学习了
赞,比较详细
请教下require hook 有什么潜在的坑吗? 比如开发的调试如何,线上用require hook部署好吗?
@whwnow 就是坑到是不多,但是调试确实是一个坑,现在只能用console
来调试。关于线上的问题,我具体咨询过成银大哥,他说线上的最好还是要编译过之后。
没有收藏功能?
@rupertqin 什么东西?
我自己试的时候,代码跑起来了没报错,但服务没启动,暂时没找到原因 还得请教下,我看官方文档提到polyfill这是干嘛的,需要require(“babel-polyfill”) ? 调试不能直接加断点了吗?那就这一点,开发没法用了啊
@whwnow 先说第一个问题,就是polyfill是针对编译后的,如果你是直接require-hook的话,是不需要的。还有并没有觉得加断点调试有多方便
直接用typescript
@arden 可以的,但是我觉得ts写起来不爽,要是定义那么多的类型的话,为什么不直接用java呢。而且还增加了学习成本。
@XGHeaven 我刚开始也这么觉得,但用过之后感觉还是好处蛮多的。
mark
@arden 比如说?
mark,
请问一下,babel编译的文件,怎么在node下断点调试呢?
mark
@weivea 这个暂时没有办法。其实 node 这种比较容易上手的东西,用逻辑分析一下基本都可以解决问题的。最多配合上 debug, console.log 等等工具就差不多可以了
写的很棒
@XGHeaven 我已经实现啦,webstorm原来支持sourceMap的
@weivea sourcemap不是断点呀😂
node不是原始支持所有es6 features 开启所有harmony也不行 比如import export
来自酷炫的 CNodeMD
最新的node已经支持es6的写法了,后端使用babel是多此一举吧,虽然不支持import 个人觉得require挺好
@Kaijun 你需要开启 --harmony-modules,目测是这样的
@blackjack 如果是写小项目,完全可以不用babel。node5的特性足够了
@XGHeaven 看起来是这样的, 实际没有效果! 因为ES6 Module在V8里还没有具体实现方式, 所以…
@Kaijun 我也发现了,还是老老实实的用 require 或者babel吧
@XGHeaven 恩,怎么说呢,就是可以在源码上边打断点呀,运行的是编译后的文件
mark
好东西
@weivea 还可以这样,这么神奇
mark,用转码器实现没有什么禁忌么?
mark
转换过的代码在浏览器运行出错了,出错能对得上es6源码的行数吗?
如果文件量大的话会导致项目启动很慢,以为要在启动之前babel去编译所有js后在运行,这样导致项目启动很慢很慢,不知道针对这个问题,你是如何解决的,我目前是再外面编译完在运行。