在开发web应用时编写JavaScript时,必须考虑浏览器的兼容性,以及没有实现特性时会发生什么。有些人会建议干脆不要使用它,如果我们在构建复杂的东西,这是一种痛苦的体验。
庆幸的是,一些工具允许我们不再担心支持什么,而是尽可能编写最好的代码。它们被称为transpilers。transiler是一种以源代码作为输入并生成新的源代码作为输出的工具,它具有不同的语法,但是语义上尽可能接近于原始代码,或者在理想情况下等效于原始代码。
Babel几乎是将现代JavaScript (ES2015+)转换为在旧浏览器中运行的兼容实现的标准转换器。如果您只想专注于编写JavaScript,那么它是一个完美的解决方案。
尽管Babel的主要目标是为旧(有时是当前)浏览器翻译ECMAScript (ES)的最新标准,但它还可以做更多工作。有一个预置和插件的生态系统,使得添加非标准特性成为可能。每个插件都为您的代码提供了一个新的特性/转换,而预置只是插件的集合。
准备开始
大多数情况下,CLI是最快速、最简单的入门方法。
首先安装babel:
要确保安装了Node.js
接下来,我们在package.json中添加一个npm script命令:
"scripts": {
"build": "babel src -d dist"
}
编译src源文件,输出到dist目录
运行npm脚本:
npm run build
等等! 在运行Babel之前,我们必须安装将转换代码的插件。最简单和最快的方法是添加Env preset,它根据指定的浏览器选择适当的插件。可使用:
npm install babel-preset-env --save-dev
在项目根目录下创建 .babelrc, 并配置preset:
{
"presets": ["env"]
}
.babelrc作为babel配置文件,主要使用它来设置presets和plugin,还有很多选项可用。您可以在Babel API页面中查看。
注意,取决于操作系统,默认情况下以.开头的文件会被隐藏。如果这对您来说是有问题的(或者如果您只是喜欢更少的文件),您可以将Babel设置放入package.json文件,如下所示:
{
"name": "babel-test",
"version": "1.0.0",
"babel": {
// config
}
}
执行Babel
src/main.js 写入:
let a = 1;
let b = 2;
[a, b] = [b, a];
console.log(a);
console.log(b);
执行build命令来运行编译过程:
npm run build
将转换后的代码输出到dist/main.js。
dist/main.js 最终生成的内容:
"use strict";
var a = 1;
var b = 2;
var _ref = [b, a];
a = _ref[0];
b = _ref[1];
console.log(a);
console.log(b);
你会看到let已被var替换,Babel引入了一个临时变量(由下划线表示)辅助交换。
默认情况下,如果不向preset添加任何选项,它将加载所有转换。
你也可以指定目标浏览器:
{
"presets": [
["env", {
"targets": {
"browsers": ["last 2 versions", "safari >= 7"]
}
}]
]
}
这将加载所需的转换,以支持每个浏览器的最新两个版本和大于或等于版本7的Safari。您可以在Browserlist中找到可用选项。
Babel 生态
如果希望包含的每个特性都将以插件的形式出现。看一些ES2015的例子包括:
查看完整的plugin列表
如果不想一个一个地包含所有插件。因此,有一些预先提供的presets,简化每个插件的安装过程。
三个官方presets是:
Env是最常用的,也是我们这里用的。它自动加载所有必要的转换,使您的代码兼容指定的浏览器。
React用于转换React项目中的代码,主要是增加了Flow的注解和JSX的兼容性。
Flow用于清理Flow注释中的代码。
Babel Polyfill
有些JavaScript特性无法进行语法转换,通常是因为没有等价的功能——例如Promises和generator函数。
这些特性必须在浏览器中由一个库实现,以便在代码中使用,这就是polyfill的工作。
高级用法
Babel还可以用于转换语言中尚未实现的特性。一个很好的例子是类字段建议(目前处于TC39阶段3:candidate)。这在React开发人员中尤其流行,因为它消除了将方法显式绑定到特定组件的必要性,还意味着可以将组件的状态声明为类字段(潜在地消除了对构造函数的需要)。
如果想使用类字段,需要添加babel-plugin-transform-class依赖项:
npm install --save-dev babel-plugin-transform-class-properties
.babelrc文件修改如下:
{
"presets": ["env"],
"plugins": ["transform-class-properties"]
}
你可以使用class:
class App extends Component {
state = { count: 0 };
incCount = () => {
this.setState(ps => ({ count: ps.count + 1 }));
};
render() {
return (
<div>
<p>{ this.state.count }</p>
<button onClick={this.incCount}>add one</button>
</div>
);
}
}
而且不止于此。您还可以使用Babel向该语言添加您自己的新特性,推荐阅读理解通过构建您自己的Babel插件。
其它
编写现代web应用有时需要的不仅仅是JavaScript中可用的特性。其他语言也可以翻译成兼容的JavaScript,但也可以实现其他有用的特性。
最流行的选项是TypeScript,它实现了现代的ES特性,但也添加了其他特性,尤其是在类型安全方面。
另一个极端是,在不同的类别中有完全不同的语言,从函数式语言(如PureScript)到面向对象语言(如Dart)。
最后
Babel是编写现代web应用的一个很好的选择,同时还提供所有开发人员都能理解的JavaScript,能运行于各种浏览器。
Babel不仅可以在浏览器和Node.js等平台上将ES2015+转换为es5,还可以添加不属于标准的新特性。再npm网站可以找到所有可用的 plugin或presets。
随着JavaScript的发展,浏览器厂商需要一段时间来实现最新的特性。使用Babel可以写最新的JavaScript,而不用考虑运行环境是否支持。
happy learning!