按需引入polyfill
** 参考文档:你真的会用 Babel 吗?
在开发过程中,如果我们写的代码是es6语法的,其中有很多语法如:async、Array.isArray、Object.assign等等是低版本浏览器所不支持的。为了保证我们写的es6语法能够在各个新旧客户端上撒欢跑,我们需要引入polyfill对这些新的语法进行全局注入。
不引入的结果是:页面报错
如何引入polyfill?
方法一、
全局引入polyfill:在webpack的入口文件中引入:import '@babel/polyfill' ;
它会让我们程序的执行环境,模拟成完美支持 es6+ 的环境,毕竟无论是浏览器环境还是 node 环境对 es6+ 的支持都不一样。它是以重载全局变量 (E.g: Promise),还有原型和类上的静态方法(E.g:Array.prototype.reduce/Array.from),从而达到对 es6+ 的支持。不同于 babel-runtime 的是,babel-polyfill 是一次性引入你的项目中的,就像是 React 包一样,同项目代码一起编译到生产环境。
缺点:全局引入 @babel/polyfill
的这种方式可能会导入代码中不需要的 polyfill,从而使打包体积更大
改进:使用useBuiltIns
,env 会自动根据我们的运行环境,去判断需要什么样的 polyfill,而且,打包后的代码体积也会大大减小,但是这一切要配置 useBuiltIns,而且需要你安装 babel-polyfill,并 import。它会启用一个插件,替换你的import 'babel-polyfill'
,不是整个引入了,而是根据你配置的环境和个人需要单独的引入 polyfill。
用法:
{
"presets": [
[
"@babel/env",
{
"modules": "commonjs", //设置ES6 模块转译的模块格式 默认是 commonjs
"useBuiltIns": "usage",
}
]
],
}
开启 "useBuiltIns": "usage"后,打包后文件的大小明显缩小了。从857 KiB =》610 KiB
需要注意的是useBuiltIns:false
与useBuiltIns:entry
的打包效果是一样的。并且使用了`useBuiltIns: 'usage'
之后,就不必手动在入口文件中`import '@babel/polyfill'`
,否则会有如下warning:
When setting `useBuiltIns: 'usage'`, polyfills are automatically imported when needed.
Please remove the `import '@babel/polyfill'` call or use `useBuiltIns: 'entry'` + `import '@babel/polyfill'`instead.
方法二、在babelrc文件中配置@babel/transform-runtime
{
"presets": [
[
"@babel/env",
{
"modules": "commonjs", //设置ES6 模块转译的模块格式 默认是 commonjs
}
]
],
"plugins": [
"@babel/transform-react-jsx", //如果是需要支持 jsx 这个东西要单独装一下。
"@babel/transform-runtime",
]
}
优点:transform-runtime会根据检测API是否需要重写,然后按需写入需要的API。这样就可以很大程度上减少打包文件的体积,而且 transform-runtime 不会污染原生的对象,方法,也不会对其他 polyfill 产生影响。所以 transform-runtime 的方式更适合开发工具包,库,一方面是体积够小,另一方面是用户(开发者)不会因为引用了我们的工具,包而污染了全局的原生方法,产生副作用,还是应该留给用户自己去选择。
缺点:instance 上新添加的一些方法,babel-plugin-transform-runtime 是没有做处理的,比如 数组的 includes, filter, fill
等。举个例子,在代码中写了一个filter方法,在自己的浏览器运行完美。但测试小姐姐一测,发现她在浏览器上就无法使用某个功能,调试发现是 filter 不支持,难受不😣
总结
- 打包体积:全局引入 @babel/polyfill + "useBuiltIns": "usage"的方式,可以根据环境判断要引入哪些prolyfill,这个可以有效减少打包后代码的体积;babel-polyfill 是配置了执行环境的,通过环境看你需要哪些 polyfill,而 transform-runtime,是发现我们代码需要什么 polyfill就重写哪些polyfill。所以使用transform-runtime后打包体积是小于@babel/polyfill + "useBuiltIns": "usage"的。
- 全局污染:@babel/polyfill比较暴力,会重写代码中的原生对象、方法,而transform-runtime不会。
- polyfill的广度:instance 上新添加的一些方法,babel-plugin-transform-runtime 是没有做处理的,比如 数组的 includes, filter, fill 等
转载自:https://juejin.cn/post/6844903886147289095