一、作用
Babel 是一个JS转译器,主要用于将 ECMAScript 2015(EA6)+ 版本的代码转换为向后兼容的 JavaScript (ES5)语法,以便能够运行在当前和旧版本的浏览器或其他环境中。
二、运行
babel 总共分为三个阶段:解析,转换,生成。
注意:
babel 本身不具有任何转化功能,它把转化的功能都分解到一个个 plugin 里面。
因此当我们不配置任何插件时,经过 babel 的代码和输入是相同的。
插件总共分为两种:
语法插件: 在解析这一步就使得 babel 能够解析特定的语法 。
转译插件: 在转换这一步把源码转换并输出。这也是我们使用 babel 最本质的需求。
同一类语法可能同时存在语法插件版本和转译插件版本。如果我们使用了转译插件,就不用再使用语法插件了。 转换插件将启用相应的语法插件,因此你不必同时指定这两种插件。
三、几个重要包
| 工具 | 作用 |
|---|---|
| core-js | 转换一些内置类 (Promise, Symbols等等) 和静态方法 (Array.from 等)。绝大部分转换是这里做的。自动引入。 |
| regenerator | 作为 core-js 的拾遗补漏,主要是 generator/yield 和 async/await 两组的支持。当代码中有使用 generators/async 时自动引入。 |
| helpers | 如上面的 asyncToGenerator 就是其中之一,其他还有如 jsx, classCallCheck 等等,可以查看 babel-helpers。在代码中有内置的 helpers 使用时(如上面的第一段代码)移除定义,并插入引用(于是就变成了第二段代码)。 |
四、配置文件
Babel的配置文件就是.babelrc,存放在根目录下。
使用Babel的第一步,就是配置这个文件,该文件是用来设置【预设】(组合好的一套插件,让你不需要一个一个的去按照插件了)和【插件】(具体的插件)的。
{
"presets": [
// 带了配置项,自己变成数组
["env", { // 第一个元素依然是名字,第二个元素是对象,列出配置项。
"modules": false,
"targets": {
"browsers": ["> 1%", "last 2 versions", "not ie <= 8"]
}
}],
// 不带配置项,直接列出名字
"stage-2"
],
"plugins": ["transform-runtime", "transform-vue-jsx"]
}
运行顺序:
- Plugin 先运行,从前到后顺序执行。
- Preset后执行,从后到前顺序执行。
插件和 preset 的配置项:
简略情况下,插件和 preset 只要列出字符串格式的名字即可。
但如果某个 preset 或者插件需要一些配置项(或者说参数),就需要把自己先变成数组。第一个元素依然是字符串,表示自己的名字;第二个元素是一个对象,即配置对象。
4.1 presets
babel 还提供了一组插件的集合-presets,免去一次开发者一个个添加并安装。
因为常用,所以不必重复定义 & 安装。(单点和套餐的差别,套餐省下了巨多的时间和配置的精力)
常用环境编写了一些 preset:
env
因为 env 最为常用也最重要,所以我们有必要重点关注。 env 的核心目的是通过配置得知目标环境的特点,然后只做必要的转换。
例如目标浏览器支持 es2015,那么 es2015 这个 preset 其实是不需要的,于是代码就可以小一点(一般转化后的代码总是更长),构建时间也可以缩短一些。
如果不写任何配置项,env 等价于 latest,也等价于 es2015 + es2016 + es2017 三个相加(不包含 stage-x 中的插件)。
下面列出几种比较常用的配置方法:
{
"presets": [
["env", {
"targets": {
"browsers": ["last 2 versions", "safari >= 7"]
}
}]
]
}
如上配置将考虑所有浏览器的最新2个版本(safari大于等于7.0的版本)的特性,将必要的代码进行转换。而这些版本已有的功能就不进行转化了。
这里的语法可以参考 browserslist
另外一个有用的配置项是 modules。它的取值可以是 amd, umd, systemjs, commonjs 和 false。这可以让 babel 以特定的模块化格式来输出代码。如果选择 false 就不进行模块化处理。
五、babel-loader
一些大型的项目都会有构建工具 (如 webpack 或 rollup) 来进行代码构建和压缩 (uglify)。
理论上来说,我们也可以对压缩后的代码进行 babel 处理,但那会非常慢。因此如果在 uglify 之前就加入 babel 处理,岂不完美?
在webpack中使用babel-loader
所以就有了 babel 插入到构建工具内部这样的需求。 以 webpack 为例,webpack 有 loader 的概念,因此就出现了 babel-loader。
和 babel-cli 一样,babel-loader 也会读取 .babelrc 或者 package.json 中的 babel 段作为自己的配置,之后的内核处理也是相同。唯一比 babel-cli 复杂的是,它需要和 webpack 交互,因此需要在 webpack 这边进行配置。比较常见的如下:
module: {
rules: [
{
test: /.[ejt]s$/,
use: ['cache-loader','babel-loader'],
exclude: /node_modules/
},
]
}
// 遇到JS文件就先用babel-loader处理。
可以这样理解babel-loader:
相当于一个交通枢纽,只是在webpack打包时遇到js,ts文件,交给babel去处理,
至于怎么处理,就跟webpack就没有关系了,跟babel配置有关。babel通过babelrc里面配置的内容去处理js,ts文件。