此篇来解决上篇提出的问题,官方给出babel-polyfill
和 babel-runtime
两种解决方案来解决这种全局对象或全局对象方法不足的问题
1. babel-polyfill
babel-polyfill
会在应用中模拟一个 es2015+ 的环境,对新语法需要的新对象进行补全
使用 babel-polyfill
后,可以使用内置对象如 Promise
、WeakMap
,静态方法如 Array.from
、Object.assign
,实例方法如 Array.prototypes.includes
以及 generator
函数
下载 babel-polyfill
npm i babel-polyfill --save
因为这是一个
polyfill
(需要在你的源代码之前运行),所以需要它是一个dependency
,而不是devDependency
1.1 几种引入方式
引入方式很简单,在入口文件引入 babel-polyfill
就好了
require('babel-polyfill')
或者es6的 import 'babel-polyfill'
如果是使用 webpack 可在 webpack.config.js
进行如下配置
module.exports = {
entry: ["babel-polyfill", "./app/js"],
};
1.2 babel-polyfill 的一些缺陷
babel-polyfill
可能会增加很多根本没有用到的 polyfill;- 可能会污染子模块的局部作用域,严重的可能会导致冲突
使用 babel-polyfill
前的包大小
使用 babel-polyfill
后的包大小
2. babel-runtime
接着是 babel-runtime
,简单说 babel-runtime
更像是一种按需加载的实现,比如你哪里需要使用 Promise
,只要在这个文件头部 import Promise from 'babel-runtime/core-js/promise'
就行了
下载 babel-runtime
npm install --save babel-runtime
不过如果你许多文件都要使用 Promise
,难道每个文件都要 import
一遍不成?
当然不是,Babel 官方已考虑这种情况,只需要使用 babel-plugin-transform-runtime
就可以解决手动 import 的苦恼了
2.1 babel-plugin-transform-runtime
在下载 babel-runtime
的基础上,下载 babel-plugin-transform-runtime
npm install --save-dev babel-plugin-transform-runtime
然后在 .babelrc
进行配置
{
"plugins": ["transform-runtime"]
}
2.1.1 技术细节
总的来说,babel-plugin-transform-runtime
就是可以在我们使用新 API 时自动 import babel-runtime
里面的 polyfill,具体插件做了以下三件事情:
- 当我们使用 async/await 时,自动引入
babel-runtime/regenerator
- 当我们使用 ES6 的静态事件或内置对象时,自动引入
babel-runtime/core-js
- 移除内联babel helpers并替换使用
babel-runtime/helpers
来替换
使用 babel-plugin-transform-runtime
前包的大小
使用 babel-plugin-transform-runtime
后包的大小
2.2 babel-runtime 的优劣势
此处说的优缺点是默认使用了
babel-plugin-transform-runtime
优势
- 不会污染全局变量
- 多次使用只会打包一次
- 依赖统一按需引入,无重复引入,无多余引入
- 避免 babel 编译的工具函数在每个模块里重复出现,减小库和工具包的体积
劣势
- 不支持实例化的方法如
Array.includes(x)
就不能转化 - 如果使用的API用的次数不是很多,那么
transform-runtime
引入polyfill的包会比不是transform-runtime
时大
3. 总结
babel-polyfill
是在原有的JS内置对象及方法上做向后兼容的处理,比如说ES5里面的 Object
是没有自带 assign
方法的,那么你加载了babel-polyfill
之后,它就给 Object
扩展了一个 assign
方法,这样你就可以直接使用 Object.assign(obj1, obj2)
了
而 babel-runtime
的方式则需要babel作为工具,在转换的过程中,检测到你使用了 Object.assign
,而且你的 .babelrc
配置中需要对其做ES5兼容处理,那么结合 babel-plugin-transform-runtime
,在该JS文件中引入 Object.assign
的Polyfill,这样也能实现 Object.assign
的功能,但是你无法在 Object
上直接找到 assign
的方法