这个文档涵盖了所有你想知道的关于 Babel 及其相关工具使用的所有内容。
babel-cli
babel-register
babel-node
babel-core
.babelrc
babel-preset-es2015
babel-preset-react
babel-preset-stage-x
babel-polyfill
babel-runtime
Babel 是一个用于 JavaScript 的通用多用途编译器,使用 Babel 可以使用(或创建)下一代 的JavaScript,以及下一代 JavaScript 工具。
作为一门语言,JavaScript 不断发展,带来了很多新的规范和建议,使用 Babel 可以让你在这些新的规范和建议全面普及之前就提前使用它们。
Babel 通过将最新标准的 JavaScript 代码编译为已经在目前可以工作的代码来实现上一段提到的内容。这个过程被称为 “源代码到源代码” 的编译,这也被成为 “转换”。
例如,Babel 可以将最新的 ES2015 的箭头函数语法从:
const square = n => n * n;
转换成下面的内容:
const square = function square(n) {
return n * n;
};
然而,Babel 可以胜任更多的工作,因为Babel 支持语法扩展,例如 React 的 JSX 语法或者静态类型检查的 Flow 语法。
更近一步,在 Babel 中一切皆插件,而每个人都可以充分利用 Babel 的强大能力来创建属于自己的插件。且 Babel 被组织成几个核心的模块,允许用户利用这些模块来构建下一代 JavaScript 工具链。
许多人也是这样去做的,Babel 的生态系统正在茁长的成长。在这本 Babel 手册中,我将讲解 Babel 内建的一些工具以及社区里的一些拥有的工具。
因为 JavaScript 社区没有标准的构建工具,框架或平台等,Babel 官方性与其他所有的主要工具进行了集成。无论是来自 Gulp、Browserify,或者是 Ember、Meteor,亦或是 Webpack 等,无论你的启动工具是什么,Babel 都存在一些官方性的集成。
就本手册而言,我们将介绍设置Babel的内置方法,但是您也可以访问交互式设置页面[1]以了解所有集成。
注意:本指南将参考诸如
node
和npm
之类的命令行工具。在继续进行任何操作之前,您应该对这些工具感到满意。
babel-cli
Babel的CLI是从命令行使用Babel编译文件的简单方法。
让我们首先在全局安装它以学习基础知识。
$ npm install --global babel-cli
我们可以像这样编译我们的第一个文件:
$ babel my-file.js
这会将编译后的输出直接转储到您的终端中。要将其写入文件,我们将指定 --out-file
或 -o
。
$ babel example.js --out-file compiled.js
# or
$ babel example.js -o compiled.js
如果我们想将整个目录编译成一个新目录,可以使用 --out-dir
或 -d
来完成。
$ babel src --out-dir lib
# or
$ babel src -d lib
虽然您可以在计算机上全局安装Babel CLI,但最好逐个项目在本地安装它。
这有两个主要原因。
我们可以通过运行以下命令在本地安装Babel CLI:
$ npm install --save-dev babel-cli
注意:由于在全局范围内运行 Babel 通常是一个坏主意,因此您可能需要通过运行以下命令来卸载全局副本:
$ npm uninstall --global babel-cli
完成安装后,您的 package.json
文件应如下所示:
{
"name": "my-project",
"version": "1.0.0",
"devDependencies": {
"babel-cli": "^6.0.0"
}
}
现在,与其直接从命令行运行 Babel,不如将命令放入使用本地版本的 npm 脚本中。只需在您的 package.json
中添加一个 “script”
字段,然后将 babel
命令放入其中即可进行构建。
{
"name": "my-project",
"version": "1.0.0",
+ "scripts": {
+ "build": "babel src -d lib"
+ },
"devDependencies": {
"babel-cli": "^6.0.0"
}
}
现在,从我们的终端我们可以运行:
npm run build
这将以与以前相同的方式运行Babel,只是现在我们正在使用本地副本。
babel-register
运行Babel的下一个最常见的方法是通过 babel-register
。通过此选项,您仅需要文件即可运行 Babel,这可能会更好地与您的设置集成。
请注意,这并非供生产使用。部署以这种方式编译的代码被认为是不好的做法。最好在部署之前提前进行编译。但是,这对于构建脚本或您在本地运行的其他事情非常有效。
首先让我们在项目中创建一个 index.js
文件。
console.log("Hello world!");
如果我们使用 node index.js
来运行它,那么 Babel 不会编译它。因此,我们需要先设置 babel-register
。
首先安装 babel-register
。
$ npm install --save-dev babel-register
接下来,在项目中创建一个 register.js
文件,并编写以下代码:
require("babel-register");
require("./index.js");
这是在 Node 的模块系统中注册 Babel 并开始编译每个 require
的文件。
现在,我们可以使用 node egister.js
代替运行 node index.js
。
$ node register.js
注意:您不能在要编译的文件中注册 Babel。在 Babel 有机会编译文件之前,Node 正在执行文件。
require("babel-register");
// not compiled:
console.log("Hello world!");
babel-node
如果您只是通过 node
CLI 运行某些代码,则集成 Babel 的最简单方法可能是使用 babel-node
CLI,这在很大程度上只是对 node
CLI 的替代。
请注意,这并非供生产使用。部署以这种方式编译的代码被认为是不好的做法。最好在部署之前提前进行编译。但是,这对于构建脚本或您在本地运行的其他事情非常有效。
首先,请确保您已安装 babel-cli
。
$ npm install --save-dev babel-cli
**注意:**如果您想知道为什么要在本地安装此软件,请在上面的项目部分中阅读 “从项目中运行 Babel CLI”。
然后,将运行 node
的任何位置替换为 babel-node
。
如果您使用的是 npm script
,则只需执行以下操作:
{
"scripts": {
- "script-name": "node script.js"
+ "script-name": "babel-node script.js"
}
}
否则,您将需要写出通向 babel-node
本身的路径。
- node script.js
+ ./node_modules/.bin/babel-node script.js
babel-core
如果出于某种原因需要在代码中使用 Babel,则可以使用 babel-core
软件包本身。
首先安装 babel-core
。
$ npm install babel-core
var babel = require("babel-core");
如果您具有 JavaScript 字符串,则可以直接使用 babel.transform
对其进行编译。
babel.transform("code();", options);
// => { code, map, ast }
如果使用文件,则可以使用异步api:
babel.transformFile("filename.js", options, function(err, result) {
result; // => { code, map, ast }
});
如果您出于任何原因已经拥有Babel AST,则可以直接从AST转换。
babel.transformFromAst(ast, code, options);
// => { code, map, ast }
对于上述所有方法, options
可以传递指南可以从这里了解 https://babeljs.io/docs/usage/api/#options[2]。
您现在可能已经注意到,仅运行 Babel 似乎除了将 JavaScript 文件从一个位置复制到另一个位置之外没有执行任何其他操作。
这是因为我们尚未告诉 Babel 该做什么事情。
由于Babel是通用编译器,它以多种不同的方式使用,因此默认情况下它不会执行任何操作。您必须明确告诉Babel 它应该做什么。
您可以通过安装 plugins 或 presets (plugins 组)为Babel提供操作说明。
.babelrc
在我们开始告诉 Babel 怎么做之前。我们需要创建一个配置文件。您需要做的就是在项目的根目录下创建一个 .babelrc
文件。从这样开始:
{
"presets": [],
"plugins": []
}
该文件是您配置 Babel 以执行所需操作的方式。
注意:虽然您还可以通过其他方式将选项传递给 Babel,但
.babelrc
文件是约定俗成的,也是最好的方法。
babel-preset-es2015
让我们首先告诉 Babel 将 ES2015(JavaScript标准的最新版本,也称为ES6)编译为ES5(当今大多数JavaScript环境中可用的版本)。
我们将通过安装“ es2015” Babel预设来做到这一点(当然目前浏览器支持了绝大部分 ES2015 的特性了,这里是用作演示,使用形式是一致的):
$ npm install --save-dev babel-preset-es2015
接下来,我们将修改 .babelrc
以包括该预设。
{
"presets": [
+ "es2015"
],
"plugins": []
}
babel-preset-react
设置 React 同样简单。只需安装预设:
$ npm install --save-dev babel-preset-react
然后将预设添加到您的 .babelrc
文件中:
{
"presets": [
"es2015",
+ "react"
],
"plugins": []
}
babel-preset-stage-x
JavaScript还提出了一些建议,这些建议正在通过TC39(ECMAScript标准背后的技术委员会)流程纳入标准。
此过程分为5个阶段(0-4)。随着提案获得更大的吸引力,并更有可能被采纳为标准,它们经历了各个阶段,最终在阶段4被接纳为标准。
这些以babel的形式捆绑为4种不同的预设:
babel-preset-stage-0
babel-preset-stage-1
babel-preset-stage-2
babel-preset-stage-3
请注意,没有阶段 4 的 preset
,因为它只是上面的 es2015 预设。
这些预设中的每个预设都需要用于后续阶段的预设。即 babel-preset-stage-1
需要 babel-preset-stage-2
,而 babel-preset-stage-3
也需要。
安装您感兴趣的 stage 很简单:
$ npm install --save-dev babel-preset-stage-2
然后,您可以将其添加到您的 .babelrc
配置中。
{
"presets": [
"es2015",
"react",
+ "stage-2"
],
"plugins": []
}
目前,您已经使用Babel编译了代码,但这还不是故事的结局。
babel-polyfill
几乎所有未来 JavaScript 语法都可以使用 Babel 进行编译,但 API 并非如此。
例如,以下代码具有需要编译的箭头函数功能:
function addAll() {
return Array.from(arguments).reduce((a, b) => a + b);
}
在编译之后会变成如下这样:
function addAll() {
return Array.from(arguments).reduce(function(a, b) {
return a + b;
});
}
但是,由于 Array.from
并非在每个JavaScript环境中都存在,因此在编译之后它仍然无法使用:
Uncaught TypeError: Array.from is not a function
为了解决这个问题,我们使用一种叫做 Polyfill[3] 的东西。简而言之,Polyfill 是一段代码,该代码复制当前运行时中不存在的 API,允许您在当前环境可用之前能提前使用 Array.from
等 API。
Babel使用出色的 core-js[4] 作为其polyfill,以及定制的 regenerator[5] 运行时,以使生成器和异步函数正常工作。
要包含 Babel polyfill,请首先使用npm安装它:
$ npm install --save babel-polyfill
然后只需将 polyfill 包含在任何需要它的文件的顶部:
import "babel-polyfill";
babel-runtime
为了实现 ECMAScript 规范的详细信息,Babel将使用 “helper” 方法来保持生成的代码干净。
由于这些 “helper” 方法会变得很长,而且它们被添加到每个文件的顶部,因此您可以将它们移动到 require
的单个“运行时”中。
首先安装 babel-plugin-transform-runtime
和 babel-runtime
:
$ 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;
}();
而不是将 _classCallCheck
和 _createClass
helper 函数放在需要的每个文件中。
大多数人都可以通过仅使用内置预设来使用 Babel,但是 Babel 所展现的功能远不止于此。
Babel 预设只是预配置插件的集合,如果您想做不同的事情,可以手动指定插件。这几乎与预设完全相同。
首先安装一个插件:
$ npm install --save-dev babel-plugin-transform-es2015-classes
然后将 plugins
字段添加到您的 .babelrc
中。
{
+ "plugins": [
+ "transform-es2015-classes"
+ ]
}
这使您可以更精确地控制正在运行的确切的 transforms
。
有关官方插件的完整列表,请参见Babel插件页面[6]。
还请看一下社区构建的所有插件[7]。如果您想学习如何编写自己的插件,请阅读Babel插件手册[8](图雀社区将在之后翻译这本插件手册,敬请期待~)。
许多插件还具有将其配置为不同行为的 option
。例如,许多 transform
都具有 loose
模式,该模式会放弃某些规范行为,而倾向于使用更简单,性能更高的代码。
要将选项添加到插件,只需进行以下更改:
{
"plugins": [
- "transform-es2015-classes"
+ ["transform-es2015-classes", { "loose": true }]
]
}
Babel插件解决了许多不同的任务。其中许多是开发工具,可以帮助您调试代码或与工具集成。还有许多用于优化生产中代码的插件。
因此,通常需要基于环境的 Babel 配置。您可以使用 .babelrc
文件轻松完成此操作。
{
"presets": ["es2015"],
"plugins": [],
+ "env": {
+ "development": {
+ "plugins": [...]
+ },
+ "production": {
+ "plugins": [...]
+ }
}
}
Babel将根据当前环境在 env
内部启用配置。
当前环境将使用 process.env.BABEL_ENV
。当 BABEL_ENV
不可用时,它将回退到 NODE_ENV
,如果不可用,则默认为“ development
”。
$ BABEL_ENV=production [COMMAND]
$ NODE_ENV=production [COMMAND]
$ SET BABEL_ENV=production
$ [COMMAND]
注意:
[COMMAND]
是您用来运行Babel的任何东西(即babel
,babel-node
,或者如果您正在使用babel-register
钩子,则可能只是node
)。提示:如果要让命令在 Unix 和 Windows 跨平台上运行,请使用 cross-env[9]。
手动指定插件?插件选项?基于环境的设置?对于所有项目,所有这些配置似乎都需要重复很多次。
因此,我们鼓励社区创建自己的预设。这可以是您整个公司[10]的预设。
创建预设很容易。假设您有以下 .babelrc
文件:
{
"presets": [
"es2015",
"react"
],
"plugins": [
"transform-flow-strip-types"
]
}
您需要做的就是按照命名约定 babel-preset-*
创建一个新项目(请对此命名空间负责!),并创建两个文件。
首先,创建一个新的 package.json
文件,该文件具有您的预设所需的 dependencies
关系。
{
"name": "babel-preset-my-awesome-preset",
"version": "1.0.0",
"author": "James Kyle <me@thejameskyle.com>",
"dependencies": {
"babel-preset-es2015": "^6.3.13",
"babel-preset-react": "^6.3.13",
"babel-plugin-transform-flow-strip-types": "^6.3.15"
}
}
然后创建一个 index.js
文件,该文件导出 .babelrc
文件的内容,并用 require
调用替换插件/预设字符串。
module.exports = {
presets: [
require("babel-preset-es2015"),
require("babel-preset-react")
],
plugins: [
require("babel-plugin-transform-flow-strip-types")
]
};
然后只需将其发布到 npm,就可以像使用任何预设一样使用它。
一旦掌握了 Babel,Babel 便会很直接地进行设置,但是使用其他工具进行设置可能非常困难。但是,我们尝试与其他项目紧密合作,以使体验尽可能轻松。
较新的标准为语言带来了许多新语法,而静态分析工具才刚刚开始利用它。
ESLint 是最受欢迎的 Lint 工具之一,因此,我们维护了官方的 babel-eslint[11] 集成。首先安装 eslint
和 babel-eslint
。
$ npm install --save-dev eslint babel-eslint
接下来,在项目中创建或使用现有的 .eslintrc
文件,并将解析器设置为 babel-eslint
。
{
+ "parser": "babel-eslint",
"rules": {
...
}
}
现在将一个 lint
任务添加到您的 npm package.json
脚本中:
{
"name": "my-module",
"scripts": {
+ "lint": "eslint my-files.js"
},
"devDependencies": {
"babel-eslint": "...",
"eslint": "..."
}
}
然后只需运行任务即可完成所有设置。
$ npm run lint
有关更多信息,请查阅 babel-eslint[12]或eslint[13]文档。
使用Babel,ES2015和Flow,您可以推断出很多有关您的代码的信息。使用documentation.js[14],您可以非常轻松地生成详细的API文档。
Documentation.js在后台使用Babel支持所有最新语法,包括Flow注释,以便在代码中声明类型。
现在,所有主要的JavaScript框架都专注于围绕语言的未来调整其API。因此,在工具中进行了大量工作。
框架不仅有机会使用Babel,而且有机会以改善用户体验的方式对其进行扩展。
React极大地改变了其API以使其与ES2015类保持一致(在此处了解更新的API)。更进一步,React依赖Babel来编译它的JSX语法,不赞成Babel来使用它自己的自定义工具。您可以按照上述说明开始设置 babel-preset-react
程序包。
React社区接受了Babel并与之合作。社区[15]现在进行了许多转换。
最著名的是 babel-plugin-react-transform
插件,结合了许多特定于 React 的转换,可以启用热模块重装和其他调试实用程序。
[1]
交互式设置页面: https://babeljs.io/en/setup/
[2]
https://babeljs.io/docs/usage/api/#options: https://babeljs.io/docs/usage/api/#options
[3]
Polyfill: https://www.google.com/search?q=%E4%BB%80%E4%B9%88%E6%98%AF+polyfill&oq=%E4%BB%80%E4%B9%88%E6%98%AF+polyfill&aqs=chrome..69i57j0i12.3956j1j4&sourceid=chrome&ie=UTF-8
[4]
core-js: https://github.com/zloirock/core-js
[5]
regenerator: https://github.com/facebook/regenerator
[6]
Babel插件页面: http://babeljs.io/docs/plugins/
[7]
所有插件: https://www.npmjs.com/search?q=babel-plugin
[8]
Babel插件手册: https://github.com/jamiebuilds/babel-handbook/blob/master/translations/en/plugin-handbook.md
[9]
cross-env: https://www.npmjs.com/package/cross-env
[10]
公司: https://github.com/cloudflare/babel-preset-cf
[11]
babel-eslint: https://github.com/babel/babel/tree/master/eslint/babel-eslint-parser
[12]
babel-eslint: https://github.com/babel/babel/tree/master/eslint/babel-eslint-parser
[13]
eslint: https://eslint.org/
[14]
documentation.js: http://documentation.js.org/
[15]
社区: https://www.npmjs.com/search?q=babel-plugin+react
- END -