likes
comments
collection
share

按需引入polyfill

作者站长头像
站长
· 阅读数 134

**  参考文档:你真的会用 Babel 吗?

在开发过程中,如果我们写的代码是es6语法的,其中有很多语法如:async、Array.isArray、Object.assign等等是低版本浏览器所不支持的。为了保证我们写的es6语法能够在各个新旧客户端上撒欢跑,我们需要引入polyfill对这些新的语法进行全局注入。

不引入的结果是:页面报错

按需引入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,从而使打包体积更大

改进:使用useBuiltInsenv 会自动根据我们的运行环境,去判断需要什么样的 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:falseuseBuiltIns: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
评论
请登录