介绍
Babel 的用途:
一个 JS 编译器,可以帮我们把最新标准编写的 JS 代码编译成向下兼容的 JS 代码,这样我们就可以在旧的浏览器环境中进行开发
支持语法扩展,能支持像 React 所用的 JSX 语法
支持用于静态类型检查的流式语法(Flow Syntax)
Babel 的一切都是简单的插件,谁都可以创建自己的插件,利用 Babel 的全部威力去做任何事情;自身被分解成了数个核心模块,任何人都可以利用它们来创建下一代的 JavaScript 工具。
@babel/core
Babel的核心模块,可以使用 transform
方法进行编译代码
1 | $ npm i --save-dev @babel/core |
@babel/cli
一个终端运行工具,内置的插件。一种在命令行下使用 Babel 编译文件的简单方法
1 | // 安装 |
用法一:命令行的形式(在项目根目录执行语句)
解析 src 目录下的所有 JS 文件, 并将转换后的每个文件都输出到 lib 目录下
1 | npx babel src --out-dir lib |
解析指定的文件,并写入到指定的文件
1 | npx babel example.js --out-file compiled.js |
用法二:package.json 配置
1 | "scripts": { |
插件、Presets(预设)
Babel 默认情况是什么都不做,需要配置插件或者 presets(预设,一组插件)告诉 Babel 去做什么
插件本质就是一个JS
程序, 指示着Babel如何对代码进行转换
插件选项
很多插件也有选项用于配置他们自身的行为。 例如,很多转换器都有“宽松”模式,通过放弃一些标准中的行为来生成更简化且性能更好的代码。
1 | { |
一些 Presets
babel-preset-stage-x 实现阶段
JavaScript 还有一些提案,正在积极通过 TC39(ECMAScript 标准背后的技术委员会)的流程成为标准的一部分。
这个流程分为 5(0-4)个阶段。 随着提案得到越多的关注就越有可能被标准采纳,于是他们就继续通过各个阶段,最终在阶段 4 被标准正式采纳。
以下是4 个不同阶段的(打包的)预设:
babel-preset-stage-0
babel-preset-stage-1
babel-preset-stage-2
babel-preset-stage-3
注意 stage-4 预设是不存在的因为它就是上面的
es2015
预设。
以上每种预设都依赖于紧随的后期阶段预设。例如,babel-preset-stage-1
依赖 babel-preset-stage-2
,后者又依赖 babel-preset-stage-3
。.
使用的时候只需要安装你想要的阶段就可以了:
1 | npm install --save-dev babel-preset-stage-2 |
配置
1 | { |
配置 Babel
在项目的根目录下创建一个babel.config.js
文件
- babelrc: 只会影响本项目中的代码
- babel.config.js 会影响整个项目中的代码,包括node_modules中的代码
1 | const presets = [ |
使用
在 package.json 配置命令行语句,它默认会去寻找跟根目录下的一个名为babel.config.js 的文件(或者 babelrc.js)
1 | { |
Polyfill
Polyfill是对执行环境或者其它功能的一个补充
比如
edge10
浏览器中不支持ES7中的方法includes()
,Polyfill 可以帮忙引入一个环境,补充方法
1 | // 原来的代码 |
@babel/polyfill
Babel 用了优秀的 core-js 用作 polyfill,并且还有定制化的 regenerator 来让 generators(生成器)和 async functions(异步函数)正常工作
1 | 需要安装到开发环境,这是一个在源代码之前运行的 polyfill |
因为使用的是 env presets,可以设置 useBuiltIns 选项
1 | const presets = [ |
但 @babel/polyfill 在Babel7.4.0以上已经不被推荐使用了。推荐使用core-js@3
+@babel/preset-env
然后设置@babel/preset-env
的corejs
选项为3
.
按上述方法虽然可以正常转化 js,但会报错
1 | WARNING: We noticed you're using the `useBuiltIns` option without declaring a core-js version. Currently, we assume version 2.x when no version is passed. Since this default version will likely change in future versions of Babel, we recommend explicitly setting the core-js version you are using via the `corejs` option. |
解决办法是卸载掉@babel/polyfill
, 然后重新安装core-js@版本号
, 然后重新配置一些babel.config.js文件
安装
core-js@3
1
npm i --save core-js@3
添加
corejs
选项1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17const presets = [
[
"@babel/env",
{
targets: {
edge: "17",
chrome: "64",
firefox: "67",
safari: '11.1'
},
useBuiltIns: "usage",
+ corejs: 3
}
]
]
module.exports = { presets }
@babel/plugin-transform-runtime
为了实现 ECMAScript 规范的细节,Babel 会使用“助手”方法来保持生成代码的整洁。
由于这些助手方法可能会特别长并且会被添加到每一个文件的顶部,因此可以安装一些包把它们统一移动到一个单一的“运行时(runtime)”中去。
什么是助手?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 class Foo {
method() { }
}
// 编译成
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }
var Foo = /*#__PURE__*/function () {
function Foo() {
_classCallCheck(this, Foo);
}
_createClass(Foo, [{
key: "method",
value: function method() {}
}]);
return Foo;
}();安装包
1 | npm i --save-dev @babel/plugin-transform-runtime |
配置
1 | const plugins = ["@babel/plugin-transform-runtime"] |
编译后的结果
1 | var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); |
基于环境自定义 Babel
Babel 将根据当前环境来开启 env
下的配置。
当前环境可以使用 process.env.BABEL_ENV
来获得。 如果 BABEL_ENV
不可用,将会替换成 NODE_ENV
,并且如果后者也没有设置,那么缺省值是"development"
。
1 | { |
plugins 与 presets 的执行顺序
可以同时使用多个 Plugin 和 Preset,此时,它们的执行顺序非常重要。
- 先执行完所有 Plugin,再执行 Preset。
- 多个 Plugin,按照声明次序顺序执行。
- 多个 Preset,按照声明次序逆序执行。
比如 .babelrc配置如下,那么执行的顺序为:
- Plugin:transform-react-jsx、transform-async-to-generator
- Preset:es2016、es2015
1 | // .babelrc |