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 内建的一些工具以及社区里的一些领有的工具。
Babel 模块介绍
因为 JavaScript 社区没有规范的构建工具,框架或平台等,Babel 官网性与其余所有的次要工具进行了集成。无论是来自 Gulp、Browserify,或者是 Ember、Meteor,亦或是 Webpack 等,无论你的启动工具是什么,Babel 都存在一些官网性的集成。
就本手册而言,咱们将介绍设置 Babel 的内置办法,然而您也能够拜访交互式设置页面以理解所有集成。
留神:本指南将参考诸如 node
和 npm
之类的命令行工具。在持续进行任何操作之前,您应该对这些工具感到称心。
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 的不同版本,从而容许您一次更新一个版本。
- 这意味着您对工作的环境没有隐式依赖。使您的我的项目更加可移植且易于设置。
咱们能够通过运行以下命令在本地装置 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 的下一个最常见的办法是通过 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`(
);
compiled:
.log(
);`”babel-register” //__not
console”Hello world!”
如果您只是通过 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,则能够应用 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
能够传递指南能够从这里了
配置 Babel
您当初可能曾经留神到,仅运行 Babel 仿佛除了将 JavaScript 文件从一个地位复制到另一个地位之外没有执行任何其余操作。
这是因为咱们尚未通知 Babel 该做什么事件。
因为 Babel 是通用编译器,它以多种不同的形式应用,因而默认状况下它不会执行任何操作。您必须明确通知 Babel 它应该做什么。
您能够通过装置 plugins 或 presets(plugins 组)为 Babel 提供操作阐明。
在咱们开始通知 Babel 怎么做之前。咱们须要创立一个配置文件。您须要做的就是在我的项目的根目录下创立一个 .babelrc
文件。从这样开始:
`{` "presets"`: [],`
"plugins"`: []`
`}`
该文件是您配置 Babel 以执行所需操作的形式。
留神:尽管您还能够通过其余形式将选项传递给 Babel,但 .babelrc
文件是约定俗成的,也是最好的办法。
让咱们首先通知 Babel 将 ES2015(JavaScript 规范的最新版本,也称为 ES6)编译为 ES5(当今大多数 JavaScript 环境中可用的版本)。
咱们将通过装置“es2015”Babel 预设来做到站长博客这一点(当然目前浏览器反对了绝大部分 ES2015 的个性了,这里是用作演示,应用模式是统一的):
`$ npm` install --save-dev babel-preset-es2015
接下来,咱们将批改 .babelrc
以包含该预设。
`{` "presets"`: [`
`+` "es2015"
`],`
"plugins"`: []`
`}`
设置 React 同样简略。只需装置预设:
`$ npm` install --save-dev babel-preset-react
而后将预设增加到您的 .babelrc
文件中:
`{` "presets"`: [`
"es2015"`,`
`+` "react"
`],`
"plugins"`: []`
`}`
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 编译了代码,但这还不是故事的终局。
简直所有将来 JavaScript 语法都能够应用 Babel 进行编译,但 API 并非如此。
例如,以下代码具备须要编译的箭头函数性能:
function addAll() `{
.from(
).reduce(
a + b);
}` returnArrayarguments(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 作为其 polyfill,以及定制的 regenerator[5] 运行时,以使生成器和异步函数失常工作。
要蕴含 Babel polyfill,请首先应用 npm 装置它:
`$ npm` install --save babel-polyfill
而后只需将 polyfill 蕴含在任何须要它的文件的顶部:
import “babel-polyfill”;
为了实现 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 所展示的性能远不止于此。
Babel 预设只是预配置插件的汇合,如果您想做不同的事件,能够手动指定插件。这简直与预设完全相同。
首先装置一个插件:
`$ npm` install --save-dev babel-plugin-transform-es2015-classes
而后将 plugins
字段增加到您的 .babelrc
中。
`{` `+` "plugins"`: [`
`+` "transform-es2015-classes"
`+ ]`
`}`
这使您能够更准确地管制正在运行的确切的 transforms
。
无关官网插件的残缺列表,请参见 Babel 插件页面。
还请看一下社区构建的所有插件。如果您想学习如何编写本人的插件,请浏览 Babel 插件手册(图雀社区将在之后翻译这本插件手册,敬请期待~)。
许多插件还具备将其配置为不同行为的 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
”。
Unix
`$ BABEL_ENV=production [COMMAND]` `$ NODE_ENV=production [COMMAND]`
Windows
`$ SET BABEL_ENV=production` `$ [COMMAND]`
留神:[COMMAND]
是您用来运行 Babel 的任何货色(即 babel
,babel-node
,或者如果您正在应用 babel-register
钩子,则可能只是 node
)。
提醒:如果要让命令在 Unix 和 Windows 跨平台上运行,请应用 cross-env。
手动指定插件?插件选项?基于环境的设置?对于所有我的项目,所有这些配置仿佛都须要反复很屡次。
因而,咱们激励社区创立本人的预设。这能够是您整个公司的预设。
创立预设很容易。假如您有以下 .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,Babel 便会很间接地进行设置,然而应用其余工具进行设置可能十分艰难。然而,咱们尝试与其余我的项目严密单干,以使体验尽可能轻松。
较新的规范为语言带来了许多新语法,而动态剖析工具才刚刚开始利用它。
Linting
ESLint 是最受欢迎的 Lint 工具之一,因而,咱们保护了官网的 babel-eslint 集成。首先装置 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 或 eslint 文档。
应用 Babel,ES2015 和 Flow,您能够推断出很多无关您的代码的信息。应用 documentation.js,您能够十分轻松地生成具体的 API 文档。
Documentation.js 在后盾应用 Babel 反对所有最新语法,包含 Flow 正文,以便在代码中申明类型。
当初,所有次要的 JavaScript 框架都专一于围绕语言的将来调整其 API。因而,在工具中进行了大量工作。
框架不仅有机会应用 Babel,而且有机会以改善用户体验的形式对其进行扩大。
React
React 极大地扭转了其 API 以使其与 ES2015 类保持一致(在此处理解更新的 API)。更进一步,React 依赖 Babel 来编译它的 JSX 语法,不赞成 Babel 来应用它本人的自定义工具。您能够依照上述阐明开始设置 babel-preset-react
程序包。
React 社区承受了 Babel 并与之单干。社区当初进行了许多转换。
最驰名的是 babel-plugin-react-transform
插件,联合了许多特定于 React 的转换,能够启用热模块重装和其余调试实用程序。