transform-runtime 会自动应用 polyfill,即便没有使用 babel-polyfill
lmk123 opened this issue · 13 comments
先简述一下 babel-polyfill 与 transform-runtime 是做什么的。
目前浏览器对 ES2015 语法的支持都不太好,所以当我们需要使用 Promise、Set、Map 等功能时就需要 babel-polyfill 来提供。
在转换 ES2015 语法为 ECMAScript 5 的语法时,babel 会需要一些辅助函数,例如 _extend。babel 默认会将这些辅助函数内联到每一个 js 文件里,这样文件多的时候,项目就会很大。
所以 babel 提供了 transform-runtime 来将这些辅助函数“搬”到一个单独的模块 babel-runtime 中,这样做能减小项目文件的大小。
今天我在写一个针对 Chrome 浏览器的项目的时候,使用了 transform-runtime,但没有用 babel-polyfill,因为很多 ES2015 的功能(比如 Promise)Chrome 都已经支持了。可是文件经过 babel 转换之后,文件大小陡增,仔细一看,发现 babel 把 Promise 的 polyfill 给注入进来了。
因为我没有使用 babel-polyfill,所以我本来认为,babel 应该是不会给我注入任何 polyfill 的,但事与愿违。我查看了一下 babel-runtime,发现除了包含 babel 转换时需要用到的辅助函数外,它还包含了 corejs 与 regenerator——而 babel-polyfill 也包含了这两个模块。
当我查阅 transform-runtime 的文档时,才发现 transform-runtime 是可以配置的:
// with options
{
"plugins": [
["transform-runtime", {
"polyfill": false,
"regenerator": true
}]
]
}由此可见,当我们在配置里直接使用 "plugins": ["transform-runtime"] 时,其实就相当于引入了 babel-polyfill。
这可能并不是我们想要的。
奇怪的是已使用transform-runtime 但是Array.find 是undefined
@yoyeung 我刚才试了一下,不用 babel-polyfill 只用 transform-runtime 的话,Array.prototype.find 确实是 undefined。
也许在没有 babel-polyfill 的情况下,transform-runtime 只会把 built-ins(比如 Promise 和 Symbol)给加进去吧,等我有空了就验证一下。
謝謝。。。。這個問題有點困擾
我的解決方法是人工加入
@yoyeung 刚好路过,也遇到过这个问题,这其实是配置不对,官方推荐的用法是:
// with options
{
"plugins": [
["transform-runtime", {
"polyfill": false,
"regenerator": true
}]
]
}
这样是不会自动polyfill各种ES6/7方法的,只要把polyfill改成true即可,babel会自动识别代码里用到了哪些对象方法(只要不是特别奇葩的用法比如Object['assign']),并自动polyfill这些方法。而这其实是默认开启的,所以可以简写成:
// with options
{
"plugins": [
"transform-runtime"
]
}
@conanliu 不是这样吧! 当使用 transform-runtime 配置为
"plugins": [
["transform-runtime", {
"polyfill": true,
"regenerator": true
}]
]
Array.prototype.findIndex 是undefined
只有当使用babel-polyfill 时能找到Array.prototype.findeIndex
$export($export.P + $export.F * forced, 'Array', { findIndex: function findIndex(callbackfn/*, that = undefined */){ return $find(this, callbackfn, arguments.length > 1 ? arguments[1] : undefined); } });
从别的文章中我得到这么一段话:
transform-runtime 只能对语法进行解析如 await、async 等 但对Api不能够进行polyfill.
Ps: 到现在我都没能确切的理解transform-runtime到底能不能完全polyfill,以至于我们现在的解决方案是项目中使用到的新特性都会先用corejs先处理我们项目中用到了的语法和Api
@kangaoxiaoshi
You can see transform-runtime
你最上面说的这一句话:
在转换 ES2015 语法为 ECMAScript 5 的语法时,babel 会需要一些辅助函数,例如 _extend。babel 默认会将这些辅助函数内联到每一个 js 文件里,这样文件多的时候,项目就会很大。
其中的辅助函数指的是babel因为设置了babel-preset-2015转换语法而生成的,还是通过单独的一个es6的API转换插件比如babel-plugin-transform-object-assign转换生成的,还是怎么生成的?
transform-runtime默认配置polyfill为true。
"plugins": [
["transform-runtime"]
]
亲测,会转换如文档所说的构建Promise,Set,Map等实例的语法文档地址
我也试了下如Array.find等API方法,不加babel-polyfill,transform-runtime默认配置也会转换es6的API为 es5
在转换 ES2015 语法为 ECMAScript 5 的语法时??
总结:
- 第一个目的避免重复引用工具类好理解
- 第二个目的是提供运行时的helper,polyfill与regenerator支持。
babel-polyfill是全局污染的,babel-runtime则是直接重写的方法来让你使用。
那么接下来的问题是,babel-runtime到底polyfill了哪些?
引用这篇文章
它不模拟实例方法,即内置对象原型上的方法,所以类似Array.prototype.find,你通过babel-runtime是无法使用的。
但我无从考证。官方文档上如是说:
这意味着你可以无缝的使用这些原生内置的和静态方法,且无需担心它们的来源。
注意: 例如 "foobar".includes("foo") 等实例方法将不会正常工作。
@kangaoxiaoshi 只启用 transform-runtime ,Array.prototype.findIndex 已经注入了,是你版本问题?
env:
- babel-plugin-transform-runtime@6.23.0
大家要区分Array.from还是Array.prototype.findIndex。 前者是类的方法,后者是内置对象原型上的方法。 transform-runtime和babel-runtime无法polyfill对象原型上的方法~ 但能polyfill Array.from.
关于transform-runtime解决的问题,我这里有一篇比较啰嗦的实验性文章 从零搭建webpack前端类库脚手架[3]-强悍的babel
Array.prototype.findIndex
请问你是怎么用的?