babel-polyfill和transform-runtime揭秘
当前前端的开发,已经基本离不开babel
的使用了。
而babel
下两员大将babel-polyfill
和transform-runtime
也经常出现在各位前端同胞的业务及库的开发中,让我们得以欢快地使用js的各种高级语法以及牛X的api。可虽说是如此常用,很多前端同胞甚至是前端老司机也常常搞不清二者的关系,以至陷入莫名的疑惑当中。
正在这个时候,一名不愿露面的网友,本着刨根问底的钻(qiu)研(nue)精神,一窥二者的本质,向大家聊一聊两者的关系。
在此之前,让我们先了解一下core-js这个库,版本2.5.7
。打开它的github主页,如下:
我们发现,呃,作者正在找工作,这个不是重点。从这段文字中我们知道了core-js
是一个模块化的js标准库,包含着各种垫片等。重点在最后一句,我们可以按需使用,或者不污染全局命名空间地使用它。
也就是说我们至少应该有两种方式使用它:
在程序入口的最开始处引入,当成垫片使用,会污染全局命名空间。
1
require('core-js/shim')
当成一个普通的commonjs库使用,不污染全局命名空间。
1
var core = require('core-js/library')
实际上,还有第三种,一股脑全引入,同样会污染全局命名空间:
1
require('core-js')
好的,回到我们的主角当中。
babel-polyfill
我们先来看看babel-polyfill
,以版本6.26.3
为例,找到安装包的入口文件lib/index.js
,简洁的数行代码:
1 | if (global._babelPolyfill) { |
注释后面的就不用看了,将在下一个主版本发布时移除掉。然后我们看到只引入了两个库core-js/shim
和regenerator-runtime/runtime
。前者根据core-js
的第一条使用方式,是作为js垫片使用的。后者会提供一个全局函数regeneratorRuntime
,这个就厉害了 ,我们之所以能够欢快的使用async
和await
,全是它的功劳。到此我们大概知道了babel-polyfill
实际上是一种垫片技术,保证了js在各版本下的一致性。
babel-plugin-transform-runtime
再来看看babel-plugin-transform-runtime
,以6.23.0
为例,这是一个babel插件,依赖babel-runtime
,而babel-runtime
又依赖core-js
和regenerator-runtime
。是不是隐约觉得babel-polyfill
和babel-plugin-transform-runtime
已经产生了某种联系?
该插件中有一个definitions.js文件,定义了一些builtins(即浏览器内建对象、方法),及一些如Array
、Object
、Math
、String
、Number
等类的类方法的映射路径。这些路径如何映射,又映射到哪里呢?
依Array
的includes
方法举例说明,definitions.js中这样定义到:
1 | export default { |
babel
插件,是对babel
转换后的AST(抽象语法树)进行的一系列处理,该插件对我们代码中用到的类方法的处理如下:
1 | const moduleName = getRuntimeModuleName(state.opts); |
其中moduleName
默认是babel-runtime
,${moduleName}/core-js/${methods[prop.name]}
代入变量还原后就是babel-runtime/core-js/array/includes
。找到对应路径的文件,代码如下:
1 | module.exports = { "default": require("core-js/library/fn/array/includes"), __esModule: true }; |
引用了core-js/library
,根据core-js
的第二条使用方式 —— 当成一个普通的commonjs库使用,不污染全局命名空间。而且可以针对某个方法或builtins单独引入。
这里还有个疑问,看过transform-runtime
使用文档的会知道,它并不支持实例方法,如[1, 2, 3].includes(1)
将无法起作用,那上面的Array
的includes
又是什么情况呢?事实上,它仅仅是提供了一个类方法的使用,及Array.includes
,使用方式Array.includes([1, 2, 3], 1)
,第一个参数接收一个数组实例。
例如,使用transform-runtime
将
1 | const a = [1, 3] |
转换为
1 | ; |
总结
现在我们总结下两者的区别与应用场景:
babel-polyfill
提供完整的补丁,保证各浏览器下的一致性,但体积大,会污染全局变量,适合应用于业务开发当中,开发人员无需过多关注兼容性问题。transform-runtime
按需提供,不支持实例的方法,不污染全局变量,适合于库的开发
- 本文链接:https://vhtml.github.io/2018/05/02/babel-polyfill-vs-transform-runtime/
- 版权声明:本博客所有文章除特别声明外,均采用 CC BY-NC-SA 3.0 CN 许可协议。转载请注明出处!