Babel 配置用法解析 (2)

我们主要来介绍下preset-envpreset-env是一个智能预设,配置了它就可以让你用es6+去书写你的代码,而且他会按需去加载所需要的插件,让你的生活更加美好。。。接下来我们记得先install这个 @babel/preset-env一波,不配任何插件,然后我们再来看看效果如何:

/* babel.config.js */ module.exports = { presets: [ "@babel/preset-env" ], plugins: [ ] }

对应的es6语法就会变成:

/* study.js */ const study = () => {} const arr1 = [1, 2, 33] const arr2 = [...arr1] const exponentiation = 2 ** 2 // 新增API new Promise(() => {}) new Map() /* study-compiled.js */ var study = function study() {}; var arr1 = [1, 2, 33]; var arr2 = [].concat(arr1); var exponentiation = Math.pow(2, 2); // 新增API new Promise(function () {}); new Map();

你会发现es6+的语法都被编译了,我们并没有设置任何插件哦,应该也看到了新增的API方法并没有被编译,在这里我们埋下伏笔,等下文讲到polyfill的时候再治他。

Browserslist集成

关于preset-env,我们还可以提供一个targets配置项指定运行环境,就是我们可以配置对应目标浏览器环境,那么babel就会编译出对应目标浏览器环境可以运行的代码。相信有同学遇到过在低版本系统ios手机里自己的项目会白屏,其实是某些语法在ios低版本系统里不支持,这个时候我们可以直接配置ios 7浏览器环境都可以支持的代码:

/* babel.config.js */ module.exports = { presets: [ [ "@babel/preset-env", { 'targets': { 'browsers': ['ie >= 8', 'iOS 7'] // 支持ie8,直接使用iOS浏览器版本7 } } ] ], plugins: [ ] }

当然babelBrowserslist集成还支持在package.json文件里或者新建一个 .browserslistrc 文件来指定对应目标环境。

@babel/polyfill(由core-js2和regenerator-runtime组成的一个集成包)

上文也提到了像Promise这种API咱们的babel并没有给转义,那是因为babel默认是只会去转义js语法的,不会去转换新的API,比如像Promise、Generator、Symbol这种全局API对象,babel是不会去编译的,这个时候就要掏出 @babel/polyfill 了。用法很简单,先安装一波,然后我们只需要在入口文件顶部引入 @babel/polyfill 就可以使用新增的API了。

/* study.js */ import '@babel/polyfill' // 新增API new Promise(function () {}); /* study-compiled.js */ require("@babel/polyfill"); // 新增API new Promise(function () {});

小细节:import被编译成了require,如果想要编译出来的模块引入规范还是import,则可以在preset-env的配置项中添加"modules": false即可。
modules的options:"amd" | "umd" | "systemjs" | "commonjs" | "cjs" | "auto" | false,默认为"auto"

但是问题又来了,有时候我们项目里并没有用到那么多的新增API,但是 @babel/polyfill 会把所有浏览器环境的的polyfill都引入,整个包的体积就会很大,我们想要对目标环境按需引入相应的polyfill应该怎么办呢,这个时候我们就可以使用 preset-env 的配置项中的useBuiltIns属性来按需引入polyfill。

/* babel.config.js */ module.exports = { presets: [ [ "@babel/preset-env", { "modules": false, "useBuiltIns": "entry", 'targets': { 'browsers': ['ie >= 8', 'iOS 7'] // 支持ie8,直接使用iOS浏览器版本7 } } ] ], plugins: [ ] }

这个时候就会在入口处只把所有ie8以上以及iOS 7浏览器不支持api的polyfill引入进来。

最终效果:

/* study.js */ import '@babel/polyfill' // 新增API new Promise(function () {}); /* study-compiled.js */ import "core-js/modules/es6.array.copy-within"; import "core-js/modules/es6.array.every"; ...//省略若干 import "core-js/modules/web.immediate"; import "core-js/modules/web.dom.iterable"; import "regenerator-runtime/runtime"; // 新增API new Promise(function () {});

此时你会发现,import '@babel/polyfill'没有了,引入的是我们目标环境相应的polyfill。但是有没有发现引入的都是import 'core-js/...'的内容,标题已经说啦,@babel/polyfil是由core-js2和regenerator-runtime组成的一个集成包。

这个时候你又会想,假如我的项目里面只用到了Promise这个API,能不能只给我引入Promise相应的API呢?答案是必可以!,让我们先来好好了解下preset-env的配置项中的useBuiltIns属性。

useBuiltIns

选项:"usage"| "entry"| false,默认为false。

entry我们已经用过了,意义就是在入口处将根据我们配置的浏览器兼容,将目标浏览器环境所有不支持的API都引入。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wsxpww.html