blog
blog copied to clipboard
Babel相关配置备忘
Babel介绍
Babel 把用最新标准编写的 JavaScript 代码(ES6, ES7)向下编译成可以在今天随处可用的版本(ES3,ES5)。 这一过程叫做“源码到源码”编译, 也被称为转换编译。并且还可以支持React的JSX写法。
15 年 11 月,Babel 发布了 6.0 版本。相较于前一代 Babel 5,新一代 Babel 更加模块化, 将所有的转码功能以插件的形式分离出去,默认只提供 babel-core。原本只需要装一个 babel ,现在必须按照自己的需求配置,无需下载大量无用的依赖
在命令行中使用 Babel
因为 Babel 的不同版本以及不同转码规则会起到不同的效果,全局安装会带来不必要的麻烦。在命令提示符中转到自己的项目目录下:
$ npm install --global babel-cli
# or
$ npm install --save-dev babel-core
- 如果你只想在命令行中使用babel 只需安装
babel-cli
- 如果是要在Node上以编程的方式来使用 Babel ,则需要安装
babel-core
babel-core
的作用是把js
代码分析成ast
,方便各个插件分析语法进行相应的处理。有些新语法在低版本 js 中是不存在的,如箭头函数,rest 参数,函数默认值等,这种语言层面的不兼容只能通过将代码转为 ast,分析其语法后再转为低版本js
。首先安装babel-core
。
如果你之前执行了全局安装,可以通过下面的代码卸载全局范围的 Babel。放心,这并不会影响到项目路径下的本地安装。
npm uninstall --global babel-cli
添加相关的plugin和preset
因为在babel6
中没有默认的转换规则,当你没加任何配置去转换一个文件时,babel
只会把文件直接原码输出,不做任何的改变
如果你想转义一些相关的新特性,例如 arrow function
你需要先安装arrow function
的相关plugin
npm install --save-dev babel-plugin-transform-es2015-arrow-functions
然后修改本地的.babelrc
文件,加入以下的配置
{
"plugins": ["transform-es2015-arrow-functions"]
}
// before
var foo = () => {
console.log('foo')
}
//after
'use strict';
var foo = function foo() {
console.log('foo');
};
babel的plugin是往下兼容的,比如在
ES2015
中常量是let
,如果你想在ES5中运作则需额外的添加plugin编译
$ npm install --save-dev babel-plugin-check-es2015-constants
$ npm install --save-dev babel-plugin-transform-es2015-block-scoping
{
"plugins": [
"check-es2015-constants",
"transform-es2015-block-scoping"
]
}
由于这些的依赖很难去记住,如果你不想刻意去定制,你只要配一下preset
(就是一堆插件的集合)
preset
类似于餐厅的套餐。如 babel-preset-es2015
打包了 es2015 的特性,babel-preset-stage-0
打包处于Strawman 初稿
阶段的语法,babel-preset-react
包含了React的转码规则
babel-preset-stage-x的意义
以下是babel
在4 个不同阶段的预设:
- babel-preset-stage-0
- babel-preset-stage-1
- babel-preset-stage-2
- babel-preset-stage-3
注意 stage-4 预设是不存在的因为它就是上面的 es2015 预设。
JavaScript 还有一些提案,正在积极通过 TC39(ECMAScript 标准背后的技术委员会)的流程成为标准的一部分。 这个流程分为 5(0-4)个阶段。 随着提案得到越多的关注就越有可能被标准采纳,于是他们就继续通过各个阶段,最终在阶段 4 被标准正式采纳。
- 阶段 0: Strawman 初稿
一个推进 ECMAScript 发展的自由形式的想法。该想法必须由 TC39 的会员提交,如果是非会员则必须注册成为 TC39 贡献者才能提交。
- 阶段 1:Proposal 建议
必须确定一位带头人来为负责这份建议。无论是带头人或者联合带头人都必须是 TC39 的会员(原文)。建议要解决的问题必须以简明的文字描述,而解决方案则要给出相应的实例和 API,并详细描述语义及算法。最后,必须指明此建议的潜在问题,例如与其他特性之间的关联,实现难点等。
- 阶段 2:Draft 草案
草案是规范的第一个版本。其与最终标准中包含的特性不会有太大差别。建议此时必须要附加该特性的语法和语义的正式说明(使用 ECMAScript 标准的形式语言)。说明应该尽可能完善,但可以包含待办事项和占位符。该特性需要两个实验性的实现,其中一个可以在类似 Babel 的转译器(transpiler)中实现。
- 阶段 3:Candidate 候选
候选阶段,建议基本完成,此时将从实现过程和用户使用两方面获取反馈来进一步完善建议。必备条件:规范文档必须是完整的。指定的评审人(由 TC39 而不是带头人指定)和 ECMAScript 规范的编辑须在规范上签字。还有至少要两个符合规范的实现(不必指定默认实现)。
- 阶段 4:Finished 完成
建议已经准备就绪,可以添加到标准之中。
运行Babel 生成的代码
Babel 默认只转码 ES6 的新语法(syntax),而不转换新的API,比如 Iterator、Generator、Set、Maps、Proxy、Reflect、Symbol、Promise 等全局对象,以及一些定义在全局对象上的方法(比如 Object.assign、Array.from)都不会转码。如果想让这写方法运行, babel 社区提供两种方案可以选择
- babel-polyfill
- babel-runtime + babel-plugin-transform-runtime
两个方案功能几乎相同,就是转码新增 API ,模拟 ES6 环境,但实现方法完全不同
babel-polyfill
的做法是将全局对象通通污染一遍,比如想在 node 0.10 上用 Promise,调用 babel-polyfill
就会往 global 对象挂上Promise
对象。对于普通的业务代码没有关系,但如果用在模块上就有问题了,会把模块使用者的环境污染掉。
babel-runtime
的作用也是模拟 ES2015 环境。只不过,babel-polyfill
是针对全局环境的,引入它,我们的浏览器就好像具备了规范里定义的完整的特性 – 虽然原生并未实现。babel-runtime
更像是分散的 polyfill 模块,我们可以在自己的模块里单独引入,比如 require(‘babel-runtime/core-js/promise’)
,它们不会在全局环境添加未实现的方法,只是,这样手动引用每个 polyfill
会非常低效。我们借助 Runtime transform 插件来自动化处理这一切。
$ npm install --save-dev babel-plugin-transform-runtime
$ npm install --save babel-runtime
// babelrc文件
{
"plugins": [
"transform-runtime",
"transform-es2015-classes"
]
}
现在,Babel 会把这样的代码:
class Foo {
method() {}
}
编译成:
import _classCallCheck from "babel-runtime/helpers/classCallCheck";
import _createClass from "babel-runtime/helpers/createClass";
let Foo = function () {
function Foo() {
_classCallCheck(this, Foo);
}
_createClass(Foo, [{
key: "method",
value: function method() {}
}]);
return Foo;
}();