概要
babel本身是一个工具,负责将es6/es7的代码转换成es5的代码,以便在现代浏览器里面运行,更重要的是,babel的扩展机制使其可以为React转换jsx,为Flow做静态语法分析。
babel由各种小模块组成,它通过预置一些插件来转换代码,我们接下来会谈到。
注意: 假设你本地安装了node和npm,且不排斥使用命令行工具,同时确保你的项目里面包含pajkage.json文件;
babel-cli
Babel CLI通过命令行实现代码的转换,你可以通过 npm install babel-cli -g 全局安装它,当然也可以在本地项目目录下执行 npm install babel-cli –save-dev 实现本地安装,
这里推荐项目本地安装的方式,主要有以下两个优势:
1.不同的项目本身对babel的版本依赖会有所差异,防止强依赖;
2.项目本身依赖的babel版本可以任意*灵活管控;
项目安装完 babel-cli 依赖之后,你就可以在控制台输入以下指令:
1 |
babel example.js --out-file compiled.js |
指令每部分的含义:
- babel 调用babel cli;
- example.js 指定的需要转换的es6/es7文件;
- –out-file babel 编译选项,代表编译完的文件输出信息,可以简写成 -o,如果需要编译目录文件,则输出项用 –output-dir ,可以简写成 -d;
- compiled.js - 指定输出的文件名;
每次改完代码都敲一遍指令,显然是件繁琐的事,我们可以通过给package.json的scripts配置一条构建任务指令,实现该步骤的自动化:
1 |
{ |
以上-w指令代表babel会监视src目录下的文件变化,如变化就执行重新编译该代码并输入到lib目录下;
babel-register
babel-register 通过绑定node的require函数,通过钩子函数实现在线代码转换;这种方式不推荐在生产环境使用,由于实时代码转换会带来性能的损耗而导致体验低下,所以更优的方式是代码部署前先完成代码的转换;
不过开发环境使用还是很方便的,可以实现直接编译并执行代码,那如何使用babel-register呢?
首先需要通过以下指令安装 babel-register
1 |
npm install babel-register --save-dev |
创建一个简单es6/es7文件 index.js:
1 |
const sayHello = () => {console.log('hello')}; |
创建新文件去require index.js文件 register.js:
1 |
require('babel-register'); |
当我们运行 node register.js时,控制台会输出 hello;
babel-node
如果想快速的执行一个需babel转换的文件,最好的方式是使用 babel-node 命令, 该方式同样不建议在生产环境使用,理由同上,安装了babel cli天然就携带了babel-node,如何使用呢?
首先 创建一个简单es6/es7文件 index.js:
1 |
const sayHello = () => {console.log('hello')}; |
接下来直接 babel-node index.js ,接下来就可以在控制台看到 hello 的输出;
Configuring Babel
正如之前所说,如果你不告知babel该做什么,babel本事不会做任何事情,除了将文件从一个地方挪到另一个地方,所以我们必须给babel提供presets和plugins配置来告知babel如何工作。
.babelrc
.babelrc 文件是babel的配置文件,大概的文件结构如下
1 |
{ |
现在假设我们要通过babel的配置文件告知babel将一份基于标准 es6 React的代码转成es5,如何做?
- 首先我们需要安装es2015的preset和React的preset;
1 |
npm install babel-preset-es2015 --save-dev |
- 更新 .babelrc , 添加preset配置即可;
1 |
{ |
那如果我们的代码文件里面用了许多es6草案阶段(Draft)的语法时,babel需要额外添加什么preset呢,众所周知,一个标准的js规范需要经历5个阶段(Strawman, Proposal, Draft, Candidate, Finished),才会最终纳入标准,而草案阶段是很有可能最终纳入标准的, babel通过预置不同阶段的preset完成相应转换工作,主要有以下4个:
- babel-preset-stage-0
- babel-preset-stage-1
- babel-preset-stage-2
- babel-preset-stage-3
之所以没有 babel-preset-stage-5 , 是因为它就是 babel-preset-es2015
以上每个stage的preset都依赖它后一个preset,例如babel-preset-stage-1依赖于 babel-preset-stage-2 和 babel-preset-stage-3
所以要支持草案阶段的语法只要先安装对应的preset,
1 |
npm install babel-preset-stage-2 |
然后更改babel配置文件即可:
1 |
{ |
babel-polyfill
babel-polyfill 会模拟整个es6环境,例如在没有polyfill的情况下,以下代码:
1 |
function () { |
会转换成
1 |
function () { |
这段代码其实在很多浏览器(低版本的qq浏览器,百度浏览器等)下并不能正常工作,由于它们的js内核并不支持Array.from api:
1 |
Uncaught TypeError: Array.from is not a function |
为了解决这个问题,我们需要添加一个polyfill, 一个polyfill本身就是一个代码片段,它实现了当前js运行环境未实现的本地api,babel采用corejs作为它的polyfill,采用 regenerator支持generators和async函数;
要支持babel polyfill功能,首先需要安装它:
1 |
npm install babel-polyfill --save-dev |
然后在任何需要用到polyfill的文件的顶部引用该文件:
1 |
import 'babel-polyfill'; |
babel高级配置
很多人只是用babel 内置些 presets去完成一些工作,但其实babel的能力远不仅如此:
手工配置插件
babel的presets本身就是一系列预置的插件,如果你想添加一些特殊的支持,你可以手工添加额外的插件,例如你想让你的代码支持es7 的decorators,你只要先安装对应的decorators插件:
1 |
npm install babel-plugin-transform-decorators --save-dev |
然后添加到.babelrc文件中即可:
1 |
{ |
你可以在babel官网查看babel 官方插件列表,你也可以在npm仓库查看开源社区贡献的babel插件列表
有些插件还可以额外添加一些配置项,例如很多插件会包含一个 “loose” 配置项用来指定 丢弃一些标准规范的行为,以便生成更简单,更健壮的代码;
1 |
{ |
分环境配置babel
babel有很多插件提供了对开发过程中的支持,同时也有很多插件提供了对生产环境的代码优化,你可以通过指定不同环境动态加载不同的babel插件:
1 |
{ |
当前的上下文环境是根据 process.env.BABEL_ENV 获取的,若没有,则尝试从 process.env.NODE_ENV 获取,若NODE_ENV也没有,则默认是 development 环境;
以下是分别在Unix和Windows系统上设置环境变量的方式:
Unix:
1 |
$ BABEL_ENV=development |
Windows:
1 |
$ SET BABEL_ENV=development |
当然更好的方式是使用类似cross-env的npm 包,它可以让你通过脚本参数指定环境变量。
构建自己的babel配置
每次写相同的babel配置文件其实很浪费时间,所以我们需要构建自己的presets模块
假设有如下的 .babelrc
1 |
{ |
接下来你要做的就是命名该项目 babel-preset-* ,然后创建两个文件:
一个 package.json 文件:
1 |
{ |
然后,创建一个 index.js 文件并导出 .babelrc 的上下文,将文件中的preset和插件改为用require的方式调用:
1 |
module.exports { |
最后将它发布到npm仓库即可;
其它工具
babel也可以和其它工具例如 linting,代码风格 配合一起使用
Linting
最有名的Linting工具非eslint莫属,babel将其整合到官方支持,首先,我们需要安装对应的包:
1 |
npm install eslint babel-eslint --save-dev |
接下来,在你的项目下创建 .eslintrc 文件,并做配置:
1 |
{ |
最后在你的package.json配置lint脚本,然后执行npm run lint即可:
1 |
{ |
编辑器插件
由于babel使用者越来越多,各大ide也提供了相应的babel插件支持
总结
babel和其周边的生态在当今web开发中扮演越来越重要的角色,通过这篇文章的介绍,你可以通过配置尽情的使用最新的js规范及周边技术(JSX, Flow, 等等),话不多说,赶快开始吧!