Babel默认只转换JS语法,而不转换新的API,比如Iterator、Generator、Set、Maps、Proxy、Reflect、Symbol、Promise等全局对象,以及一些定义在全局对象上的方法(比如Object.assign
)都不会转码。
举例来说,ES2015在Array
对象上新增了Array.from
方法。Babel 就不会转码这个方法。如果想让这个方法运行,必须使用babel-polyfill。(内部集成了core-js和regenerator)
npm install babel-polyfill --save
使用时,在所有代码运行之前增加require('babel-polyfill')
。或者更常规的操作是在webpack.config.js中将babel-polyfill
作为第一个entry。因此必须把babel-polyfill作为dependencies
而不是devDependencies。
注意: 在你的整个应用里只使用一次
require("babel-polyfill")
。多次import
或require
babel-polyfill会引起报错,因为它可能导致全局冲突和其他难以追踪的问题。 我们建议创建一个只包含require
语句的单个入口文件。
Array.from
,但它把Object.defineProperty
也给加上了,这就是一种浪费了。可以通过单独使用core-js
的某个类库来解决,比如通过引入babel-runtime/core-js/promise
来获取Promise
但是这样需要我们认为判断并且手动引入类库,太麻烦了。
安装:
npm install --save-dev babel-plugin-transform-runtime
npm install --save babel-runtime
然后在.babelrc
中:
{
"plugins": ["transform-runtime"]
}
启用插件babel-plugin-transform-runtime后,Babel就会使用babel-runtime下的工具函数,将Promise
重写成_Promise
(只是打比方),然后引入_Promise helper
函数。这样就避免了重复打包代码和手动引入模块的痛苦。
由于采用了沙盒(Sandbox)机制,不会污染全局变量,同时也不会去修改内建类的原型,带来的坏处是它不会polyfill原型上的扩展(例如 Array.prototype.includes()
不会被polyfill,Array.from()
则会被polyfill)
在Babel7中引入了babel-preset-env,根据你支持的环境自动决定适合你的Babel插件。
npm install babel-preset-env --save-dev
在没有任何配置选项的情况下,babel-preset-env与babel-preset-latest(或者babel-preset-es2015,babel-preset-es2016和babel-preset-es2017一起)的行为完全相同。
下面例子包含了支持每个浏览器最后两个版本和safari大于等于7版本所需的polyfill和代码转换:
{
"presets": [
["env", {
"targets": {
"browsers": ["last 2 versions", "safari >= 7"]
}
}]
]
}
如果你目标开发Node.js而不是浏览器应用的话,你可以配置babel-preset-env仅包含特定版本所需的polyfill和transform:
{
"presets": [
["env", {
"targets": {
"node": "6.10"
}
}]
]
}
按需加载babel-polyfill的关键是useBuiltIns
选项,默认值为false
,它的值有三种:
false
: 不对polyfills做任何操作entry
: 根据target
中浏览器版本的支持,将polyfills拆分引入,仅引入有浏览器不支持的polyfillusage
(新):检测代码中ES6/7/8等的使用情况,仅仅加载代码中用到的polyfills这个选项可以启用一个新的插件来替换语句import "babel-polyfill"
或者require("babel-polyfill")
以及基于浏览器环境的babel-polyfill个性化需求。
我们需要将选项值设为usage
,然后它会在每个JS文件运行,分析根据每个文件用到的语言特性导入相关的polyfill,例如
import "core-js/modules/es6.promise";
var a = new Promise();
当然分析可能会有错误,例如:
import "core-js/modules/es7.array.includes";
a.includes // assume a is an []
babel-preset-env会假设a
是数组,所以会导入相关的es7的includes
方法
这样我们就真正实现了按需加载,会让我们打包后的代码大大减小。