Babel
ECMAScript 的变化
ECMAScript Current Proposals
- stage0 只是一个美好激进的想法,有 Babel 插件实现了对这些特性的支持,但是不确定是否会被定为标准;
- stage1 值得被纳入标准的特性;
- stage2 该特性规范已经被起草,将会被纳入标准里;
- stage3 该特性规范已经定稿,各大浏览器厂商和 Node.js 社区开始着手实现;
- stage4 在接下来的一年将会加入到标准里去。

Babel的作用
- 想在代码中使用新的js语法提议,例如async/await
- 添加对新的框架语法的支持,例如jsx
- 添加对新的语言支持,例如Flow and TypeScript
ES特性分类
分为三种
- 最新ES 语法:比如,let, const, 箭头函数,import,解构赋值,对象属性展开,class, jsx, flow 等等
- 最新ES API:,比如,Promise,Aync/await等等
- 最新ES 实例方法:比如,String.protorype.includes
Babel处理方法
- 对于上述第1种新的ES语法,Babel通过plugin的方式进行转换,把新的语法转换成为ES5支持的语法,例如transform-es2015-arrow-functions
- 对于上述2,3种特性,Babel通过添加polyfills进行兼容
插件列表
Babel 插件列表
Babel工作原理
Babel 的三个主要处理步骤分别是:
解析(parse),转换(transform),生成(generate)。

Babel变化
-
Babel7 不再建议使用stage-x presets,而是根据你配置的目标环境的兼容情况来加载相应的plugins
各 stage 的插件
-
Babel7 配置的语法也发生变化,包的名字和插件名字都变化了
Babel配置的语法
{
"presets": [//数组
"presetA", // 字符串
["presetA"], // 数组包裹的字符串
["presetA", {}]// 数组,第一项是字符串,第二项是个对象,对象里面配置各种属性
],
"plugins": [
"plugin-A",
["plugin-A"],
["plugin-A", {}]
]
}
- 执行的顺序
plugins是先于presets之前执行
- 配置项的执行顺序
presets 的执行顺序是倒序,最后一个先执行,最后执行的是第一个
而plugins的执行顺序是顺序,按照配置的顺序依次执行
// presets执行顺序:倒序,下面的preset的执行属性是c,b,a
{ "presets":
[
"a",
"b",
"c"
]
}
// plugins是顺序执行,依次执行array-includes,transform-class-properties,transform-decorators-legacy
{
"plugins": [
"array-includes",
"transform-class-properties",
"transform-decorators-legacy"
]
}
Babel的使用方法
- 自己根据代码用到的语法,自己添加相应的polyfill和配置需要的plugins
- 使用presets
presets
-
如果没有配置presets和plugins,babel是如何选择哪些插件进行处理?
如果没有配置presets,babel什么也不转换
-
babel推荐使用preset-env,属性说明
targets 属性
preset-env 根据配置的targets属性,就是目标浏览器,加载需要的插件;如果没配置targes属性,默认会加载ES2015,ES2016,ES2017 需要的插件;
即使配置了targets属性,babel不会根据你代码中用到了哪些新语法而加载相应的插件,而是根据你的preset配置来加载需要的插件;如果没有配置targets属性,但是package.json配置了browserslist,会把这个属性作为targets来使用。
useBuiltIns属性(Babel7才支持下面前2中属性)
- useBuiltIns: 'entry' 导致引用了太多不需要的polyfill,因为是根据targets来决定来引用哪些polyfill
需要在入口文件中直接添加对 @babel/polyfill的引用,注意只能导入一次;例如
import "@babel/polyfill";
// 或
require("@babel/polyfill")
// 或在webpack的entry配置里添加
module.exports = {
entry: ["@babel/polyfill", "./app/js"],
};
babel根据target来替换成对应的polyfill同时把@babel/polyfill 添加到项目的依赖中,例如
npm install @babel/polyfill --save
- useBuiltIns: 'usage' 按需引用需要的polyfill,不需要在入口文件中添加引用,但依然需要把@babel/polyfill 添加到项目的依赖中
根据文件中使用情况,添加相应的polyfill
- useBuiltIns: false
不会自动添加polyfill
polyfill
Babel7 如果不设置useBuiltIns属性,babel转换时不会自动插入需要的polyfill,例如promise等,因此需要自己在代码中自行引入。
当运行环境中不支持一些方法时,babel-polyfill 会给其做兼容。 但是这样做也有一个缺点,就是会污染全局变量,而且项目打包以后体积会增大很多,当不使用useBuiltIns: 'usage'属性时,会把整个依赖包也打了进去。所以并不推荐在一些方法类库中去使用。
Babel-plugin-transform-runtime 与Babel-runtime
- Babel在转换代码时,有时候会在全局polyfill一些方法,例如,array.prototype.includs,Promise等
- 会添加一些附加的方法,例如asyncGeneratorStep, _asyncToGenerator, _createClass,_defineProperty 等等,每一个被转换的文件中都会根据需要添加对应的辅助方法
基于以上,一方面为了开发一个lib时不污染全局变量,另一方面为了减少由于辅助代码带来的冗余代码,有了Babel-runtime
runtime的使用方法
- 需要添加项目依赖babel-runtime
npm install --save @babel/runtime
- 添加dev依赖babel-plugin-transform-runtime,作为babel的一个插件使用
npm install --save-dev @babel/plugin-transform-runtime
注意: babel-runtime 不会转码实例方法,比如这样的代码,
'!!!'.repeat(3);
'hello'.includes('h');
只会通过添加相应的polyfill来处理
webpack使用
Babel
ECMAScript 的变化
ECMAScript Current Proposals
Babel的作用
ES特性分类
分为三种
Babel处理方法
插件列表
Babel 插件列表
Babel工作原理
Babel 的三个主要处理步骤分别是:
解析(parse),转换(transform),生成(generate)。
Babel变化
Babel7 不再建议使用stage-x presets,而是根据你配置的目标环境的兼容情况来加载相应的plugins
各 stage 的插件
Babel7 配置的语法也发生变化,包的名字和插件名字都变化了
Babel配置的语法
plugins是先于presets之前执行
presets 的执行顺序是倒序,最后一个先执行,最后执行的是第一个
而plugins的执行顺序是顺序,按照配置的顺序依次执行
Babel的使用方法
presets
如果没有配置presets和plugins,babel是如何选择哪些插件进行处理?
如果没有配置presets,babel什么也不转换
babel推荐使用preset-env,属性说明
targets 属性
preset-env 根据配置的targets属性,就是目标浏览器,加载需要的插件;如果没配置targes属性,默认会加载ES2015,ES2016,ES2017 需要的插件;
即使配置了targets属性,babel不会根据你代码中用到了哪些新语法而加载相应的插件,而是根据你的preset配置来加载需要的插件;如果没有配置targets属性,但是package.json配置了browserslist,会把这个属性作为targets来使用。
useBuiltIns属性(Babel7才支持下面前2中属性)
需要在入口文件中直接添加对 @babel/polyfill的引用,注意只能导入一次;例如
babel根据target来替换成对应的polyfill同时把@babel/polyfill 添加到项目的依赖中,例如
根据文件中使用情况,添加相应的polyfill
不会自动添加polyfill
polyfill
Babel7 如果不设置useBuiltIns属性,babel转换时不会自动插入需要的polyfill,例如promise等,因此需要自己在代码中自行引入。
当运行环境中不支持一些方法时,babel-polyfill 会给其做兼容。 但是这样做也有一个缺点,就是会污染全局变量,而且项目打包以后体积会增大很多,当不使用useBuiltIns: 'usage'属性时,会把整个依赖包也打了进去。所以并不推荐在一些方法类库中去使用。
Babel-plugin-transform-runtime 与Babel-runtime
基于以上,一方面为了开发一个lib时不污染全局变量,另一方面为了减少由于辅助代码带来的冗余代码,有了Babel-runtime
runtime的使用方法
注意: babel-runtime 不会转码实例方法,比如这样的代码,
只会通过添加相应的polyfill来处理
webpack使用