usage就很nb了,当配置成usage的时候,babel会扫描你的每个文件,然后检查你都用到了哪些新的API,跟进我们配置的浏览器兼容,只引入相应API的polyfill,我们把useBuiltIns属性设置为usage再来看下编译效果:
/* study.js */ import '@babel/polyfill' // 新增API new Promise(function () {}); /* study-compiled.js */ import "core-js/modules/es.object.to-string"; import "core-js/modules/es.promise"; // 新增API new Promise(function () {});我就问你帅不帅!完全的按需引入,牛逼了!
相信你也看到了一个东西,当我们使用useBuiltIns选项的时候,你的命令行里面是不是显示了一坨这样的警告,大概是在配置文件中未指定core-js版本时,默认会使用core-js2:
WARNING: We noticed you're using the useBuiltIns option without declaring a core-js version. Currently, we assume version 2.x when no version is passed. Since this default version will likely change in future versions of Babel, we recommend explicitly setting the core-js version you are using via the corejs option.
前面也说到了 @babel/polyfil 是由core-js2和regenerator-runtime组成的一个集成包,现在core-js3已经发布了,而且很稳定。但是core-js2在18年的时候已经不再维护了;@babel/polyfil引入的是2不是3,并且 @babel/polyfill 在babel7.4.0已经不再推荐使用了,要废掉(好像是因为@babel/polyfill不支持core-js2平滑的过渡到core-js3)。所以core-js官方现在推荐我们使用polyfill的时候直接引入core-js和regenerator-runtime/runtime这两个包完全取代 @babel/polyfil 来为了防止重大更改。
当然,我们需要在preset-env配置项中指定core-js版本,这样就不会再有警告⚠️了:
/* babel.config.js */ module.exports = { presets: [ [ "@babel/preset-env", { "modules": false, "useBuiltIns": "entry", "corejs": "3", 'targets': { 'browsers': ['not ie >= 8', 'iOS 7'] // 支持ie8,直接使用iOS浏览器版本7 } } ] ], plugins: [ ] }有的时候一些语法的转换会比较复杂,babel会引入一些helper函数,比如说对es6的class进行转换:
/* study.js */ class Test {} /* study-compiled.js */ function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } var Test = function Test() { _classCallCheck(this, Test); };可以看到上面引入了helper函数来处理class的转换。但是问题又来了,如果好多文件都使用到了复杂语法的转换,这个还是简单点的,有些helper函数是很复杂代码量很多的,那岂不是每个文件都会定义一遍这些个函数,每个文件的代码会很多?如果说可以把这些helper函数都抽离到一个公共的包里,用到的地方只需要引入对应的函数即可,我们的编译出来的代码量会大大滴减少,这个时候就需要用到 @babel/plugin-transform-runtime 插件来配合@babel/runtime进行使用。记得先安装一波,然后在插件选项中加入 @babel/plugin-transform-runtime 这个插件,然后我们来看看编译后的效果:
/* study.js */ class Test {} /* study-compiled.js */ import _classCallCheck from "@babel/runtime/helpers/classCallCheck"; var Test = function Test() { _classCallCheck(this, Test); };当然如果我们只是为了减少编译出来的文件中代码量而使用这个插件的话就太小看他了,而且也没有必要。
@babel/plugin-transform-runtime还有一个最重要的作用:比如说像上面我们说的Promise就需要提供相应的polyfill去解决,这样做会有一个副作用,就是会污染全局变量。如果我们只是在一个业务项目这样搞还好,也没别人要用到。但是如果我们是在维护一个公共的东西,比如公共组件库,我们这样搞,你的一些polyfill可能会把一些全局的api给改掉,副作用就会很明显,别人用你的组件库的时候就可能会出问题。@babel/plugin-transform-runtime插件为我们提供了一个配置项corejs,他可以给这些polyfill提供一个沙箱环境,这样就不会污染到全局变量,无副作用你说美不美。
记得安装 @babel/runtime-corejs2 这个包(稳定版用2就可以),注意如果不配置的话,是不会提供沙箱环境的。然后在 @babel/plugin-transform-runtime 插件配置corejs:
/* babel.config.js */ module.exports = { presets: [ [ "@babel/preset-env", { "modules": false, "useBuiltIns": "usage", "corejs": "3", 'targets': { 'browsers': ["ie >= 8", "iOS 7"] // 支持ie8,直接使用iOS浏览器版本7 } } ] ], plugins: [ [ "@babel/plugin-transform-runtime", { "corejs": 2 } ] ] }