Babel
Babel 是将 ES2015+ 的代码转换成兼容 ES2015(ES6) 的编译器。在编译过程解析-转译-输出中间,依靠众多的 plugin 支撑,提供对ES2015+语法的解析,以及支持新特性的的 polyfill 的插入,最终生成兼容 ES2015(ES6)的代码。
Babel 底层支持
-
@babel/core提供编译过程的基本支持 -
@babel/cli提供编译命令行的支持
@babel/preset-env
相比于列举一个个插件,babel 提供了方便的preset集合引入的方式,@babel/preset-env 可以根据配置可以动态的引入对应的插件集合(语法解析,polyfill特性支持)。对于JS语法的支持,@babel/preset-env基本上形成了大一统的形式。
- 主要根据以下配置动态引入相应的插件集合如下:
targets:描述支持的浏览器环境useBuiltIns:这个属性决定是否引入polyfillcorejs:表示引入哪个版本的core-js
其它集合
@babel/preset-react:提供对react jsx语法支持@babel/preset-typescript:提供对typescript语法支持,但不会做类型检查@babel/preset-flow等
Polyfill 详解
| 插件/库 | 说明 |
|---|---|
core-js | 所有 polyfill 方案都需要依赖于它, 现在有1, 2, 3版本 |
regenerator-runtime | 提供 generator, async/await 的pollyfill 是对core-js的补充 |
@babel/runtime | 提供模块化的 helper 方法 |
包含 core-js 和 regenerator runtime ,已被废弃。存在缺陷:1, 会打包所有polyfill, 2.会污染全局变量 | |
@babel/preset-env | 能根据设置加载对应的polyfill 插件,并已内联的方式插入helper以及polyfill代码,不会污染全局变量,但会造成代码冗余。对应当年的ES标准。不会提供stage-0~3的polyfill |
@babel/plugin-transform-runtime | 将内联的方式插入helper以及polyfill代码转为require引用,减少代码冗余。同样不会污染全局变量 |
综上所述: @babel/preset-env解决了polyfill的动态引入,@babel/plugin-transform-runtime 减少了内联插入的代码冗余。两者结合解决了polyfill 的引入问题。
Node 支持
@babel/node支持Node的REPL环境的所有功能,而且可以直接运行ES6代码。
废弃的插件以及 stage阶段的语法支持
-
废弃
babel-preset-es20**年份插件 -
废弃
babel-preset-stage-*proposal stage 插件- 要使用
stage-0, 1, 2, 3的语法直接引入对应的插件@babel/plugin-proposal-*
- 要使用
-
使用
npx babel-upgrade检查与升级
配置文件
配置文件优先级
babel.config.json < .babelrc < programmatic options from @babel/clior babel-loader- 同目录下,若两种类型的配置文件都存在,则
.babelrc文件会合并覆盖babel.config.json文件。 - 项目文件配置:
babel.config.json- 能够作用于
node_modules,symbollink
- 相对文件配置
.babelrc.jsonpackage.json中的babel配置,等同于.babelrc.json
执行顺序
plugins比presets先执行plugins的执行顺序是从左到右presets的执行顺序是从右到左
合并规则
- 基本上之用直接覆盖
Object.assign()合并,以下3中情况特殊 parserOpts对象的属性使用Object.assign()合并generatorOpts对象的属性使用Object.assign()合并plugins和presets使用的是合并concat数组,并去除同名的前置插件设置。
查找
Babel7开始,Babel具有“根”目录的概念,默认为当前工作目录。以下为主要的配置查找相关的配置选项,有些可以由配置文件提供,有些则是由程序化选项(programmatic options),还有一些是在脚本执行的过程中动态生成。为被解析的代码提供查找配置的依据。
| Options | 说明 | 仅程序化选项(programmatic options) | 默认值 |
|---|---|---|---|
cwd | 程序化选项中所有路径的相对工作目录 | process.cwd() | |
filename | 当前正在编译的代码对应的文件名(如果有)。文件名未知时并非所有babel的功能都可用(如:babelrc选项),因为选项的子集依赖于文件名来实现其功能。 | 是(应该是由解析过程生成) | 正在编译的代码对应的文件名 |
root | 默认的项目文件目录地址,受rootMode影响。使用场景: 1. 查找默认的 configFile值时的基本目录path.resolve(opts.root, "babel.config.json")2. 作为: babelrcRoots 的默认值 | 是 | opts.cwd |
rootMode | 决定opts.root取值的模式选项( upward upward-optional 现在最终会冒泡查找到系统的根目录,使用时要谨慎)- root: 取opts.root做根目录- upward: opts.root目录向外查找含有babel.config.json的目录作为根目录,找不到则报错- upward-optional: opts.root目录向外查找含有babel.config.json的目录作为根目录,找不到则取opts.root做根目录应用: 适用于当在 monorepos子项目中执行脚本时,向外部查找全局的公共babel配置。(因为默认情况下babel会在出现package.json 的目录停止向上检索配置文件) | 是 | root |
configFile | 显式指定项目配置文件 | 是 | path.resolve(opts.root, "babel.config.json"),找不到该文件则为false |
babelrc | 决定是否要加载相对文件配置,并作用于当前正在编译的代码。为true 时会向上查找相对于当前filename路径的相对文件配置,遇到package.json 停止。如果找到的配置不在项目文件配置的 babelrcRoots中,则会被忽略 | 当opts.filename选项有值时,为true | |
babelrcRoots | 指定哪些目录下的相对文件配置有效 | opts.root |
在查找配置的过程中,babel主要做如下工作
- 确定项目的根
opts.root - 确定
configFile文件, 根据opts.root或显式指定。此文件为项目配置文件,能够作用于项目目录中的文件,以及node_modules,symbollink - 根据
filename决定是否要查找相对文件配置,根据babelrcRoots决定是否要忽略该相对文件配置 - 合并
.babelrc.json和babel.config.json作为当前编译代码的最终配置 - 无论是 项目配置文件 还是 相对配置文件 往上搜索配置的过程中,如果在某一层找到了
package.json文件,就会停止搜索。
monorepos应用
每个package 可以设置自己的.babelrc.json,并在 项目配置文件中设置babelrcRoots
babelrcRoots: [
// 表示不要忽略根目录下的.babelrc.json
".",
// 表示不要忽略 monorepos 子目录中的.babelrc.json
"./packages/*"
]
每个package 可以设置自己的.babelrc.json,并设置rootMode
rootMode: "upward" // 或 "upward-optional"