引言
babel默认只转换新的 JavaScript 语法,比如箭头函数、spread。
不转换新的 API,例如Iterator、Generator、Set、Maps、Proxy、Reflect、Symbol、Promise 等全局对象,以及一些定义在全局对象上的方法(比如 Object.assign)都不会转译。
需要为当前环境提供一个垫片polyfill(一组代码,能够让旧的浏览器支持一些新的功能和特性),有三种:
babel-polyfill
babel-runtime
babel-plugin-transform-runtime
babel-polyfill
npm install --save babel-polyfill
因为这是一个 polyfill (它需要在你的源代码之前运行),我们需要让它成为一个 dependency,而不是一个 devDependency 。
babel-polyfill则是通过改写全局prototype的方式实现,比较适合单独运行的项目。
开启babel-polyfill的方式,可以直接在代码中require,或者在webpack的entry中添加,也可以在babel的env中设置useBuildins为true来开启。
但是babel-polyfill会有近100K,打包后代码冗余量比较大,对于现代的浏览器,有些不需要polyfill,造成流量浪费污染了全局对象
注意:你可能不需要 babel-polyfill 或者运行时插件,这取决于你实际想用 ES2015 中的哪个方法。你可能只想载入某些你正在使用的特定 polyfills (比如 Object.assign),或者只是记录加载 library 的环境应该包含特定的 polyfills 。
babel-runtime
npm install --save babel-runtime
babel-runtime 是为了减少重复代码而生的。babel-runtime插件能够将这些工具函数的代码转换成require语句,指向为对babel-runtime的引用。每当要转译一个api时都要手动加上require('babel-runtime')。
runtime转换器插件主要做了三件事:
当你使用generators/async方法、函数时自动调用babel-runtime/regenerator
当你使用ES6 的Map或者内置的东西时自动调用babel-runtime/core-js
移除内联babel helpers并替换使用babel-runtime/helpers来替换
babel-plugin-transform-runtime
以插件的形式在打包时引入到文件里,主要的功能是为api提供沙箱的垫片方案,更因此适合用在第三方的开发产品中(开发工具包,库),一方面是体积够小,另一方面是用户(开发者)不会因为引用了我们的工具,包而污染了全局的原生方法,产生副作用。
安装
在大多数情况下,你应该安装 babel-plugin-transform-runtime 作为开发依赖(使用 --save-dev)。
npm install --save-dev babel-plugin-transform-runtime
并且将 babel-runtime 作为生产依赖(使用 --save)。
因为babel编译es6到es5的过程中,babel-plugin-transform-runtime这个插件会自动polyfill es5不支持的特性,这些polyfill包就是在babel-runtime这个包里(core-js 、regenerator等)
npm install --save babel-runtime
用法
通过 .babelrc(推荐)
将以下内容添加到你的 .babelrc 文件中:
未包含选项:
{
"plugins": ["transform-runtime"]
}
包含选项:
{
"plugins": [
["transform-runtime", {
"helpers": false,
"polyfill": false,
"regenerator": true,
"moduleName": "babel-runtime"
}]
]
}
选项
辅助(helpers)
默认值是:true
表示是否开启内联的babel helpers(即babel或者环境本来的存在的垫片或者某些对象方法函数)(clasCallCheck,extends,etc)在调用模块名字(moduleName)时将被替换名字。
垫片/polyfill
默认值是:`true'
表示是否把内置的东西(Promise,Set,Map,tec)转换成非全局污染垫片。
重新生成/regenerator
默认值是:true
是否开启generator函数转换成使用regenerator runtime来避免污染全局域。
模块名字/moduleName
默认值:babel-runtime
当调用辅助(内置垫片)设置模块(module)名字/路径.
例子:
{
"moduleName": "flavortown/runtime"
}
import extends from 'flavortown/runtime/helpers/extends';
优点:
不会污染全局变量
多次使用只会打包一次
依赖统一按需引入,无重复引入,无多余引入
缺点:
不支持实例化的方法
Array.includes(x)
就不能转化如果使用的API用的次数不是很多,那么transform-runtime 引入polyfill的包会比不是transform-runtime 时大
随着应用的增大,相同的 polyfill 每个模块都要做重复的工作(检测,替换),虽然 polyfill 只是引用,编译效率不够高效。
注意:例如 foobar".includes("foo")
等实例方法将不起作用,因为这需要修改现有的内置插件(此时使用 babel-polyfill)。
Babel 使用了非常小的 helpers 来实现诸如 _extend 等常用功能。默认情况下,它将被添加到每个通过 require 引用它的文件中。这种重复(操作)有时是不必要的,特别是当你的应用程序被拆分为多个文件时。这时则需要使用 transform-runtime:所有的 helper 都会引用模块 babel-runtime,以避免编译输出的重复问题。这个运行时会被编译到你的构建版本当中。这个转译器的另外一个目的就是为你的代码创建一个沙盒环境。如果你使用了 babel-polyfill,它提供了诸如 Promise,Set 以及 Map 之类的内置插件,这些将污染全局作用域。虽然这对于应用程序或命令行工具来说可能是好事,但如果你的代码打算发布为供其他人使用的库,或你无法完全控制代码运行的环境,则会成为问题。转译器将这些内置插件起了别名 core-js,这样你就可以无缝的使用它们,并且无需使用 polyfill。