怎么给新手科普Babel:polyfill/preset-env/plugin-transform-runtime

3,630 阅读3分钟

原文:www.yuque.com/xiezhongfu/…

@babel/polyfill

更多内容参见: babeljs.io/docs/en/bab…

Babel 7.4.0 开始,这个包已经过时了,源码直接引入了 corejs 和 regenerator

image.png

图片源地址:github.com/babel/babel…

  • 应用代码里可以使用,工具库就不应该使用(下文会介绍@babel/plugin-transform-runtime)
  • 模拟了 ES6+ 环境(不包括:Stage 0/1/2/3)
  • 在程序的入口处添加,一劳永逸
  • 因为是在各 prototype 上添加 poliyfill 方法,会导致全局污染

进化方案

  1. @babel/preset-env + useBuiltIns (下文会介绍)
  2. 你自己手动单独导入你需要的 polyfill 子包

共有 2 个替代方案,推荐使用第1个,第1个方案其实就是第二个方案的自动化版本。怎么自动化呢?根据运行目标环境自动选择需要哪些 polyfill 子包。具体见下。

@babel/preset-env

更多内容参见: babeljs.io/docs/en/pre… babeljs.io/docs/en/bab…

@babel/preset-env 基于一些牛逼的项目:browserslist,compat-table,electron-to-chromium,......
@babel/preset-env 自动适配设定的目标环境需要的 js 特性,Babel 转换插件(不包含 stage-0/1/2/3的插件),corejs 的 poliyfill。自动适配可以有选择性的污染全局,当然也可以不分青红皂白全部转换到ES5,具体参见:babeljs.io/docs/en/bab…

你需要掌握在 webpack 中如何自定义配置 @babel/preset-env,掌握  @babel/preset-env + useBuiltIns 替代 @babel/polyfill 的配置。

方案1

  • 安装 @babel/polyfill
  • 在 .babelrc 中配置useBuiltIns: 'usage'

方案2

  • 安装 @babel/polyfill
  • 在应用入口处引入@babel/polyfill
  • 在 .babelrc 中配置useBuiltIns: 'entry'

方案3

  • 安装 @babel/polyfill
  • 在 .babelrc 中配置useBuiltIns: 'false' ,这是默认行为
  • 在 webpack 配置的入口处添加 @babel/polyfill

@babel/plugin-transform-runtime

更多内容参见: babeljs.io/docs/en/bab… github.com/babel/babel…

术语解释

helper:比如 Babel 使用 _extend 函数把一个对象的属性复制到另一个对象上,这里的 _extend 就是 helper

有了前两个技术方案,为什么还会出个 @babel/plugin-transform-runtime 呢?

  • 你不想污染全局
  • 你想在一个工具库中使用
  • 默认 helper 函数会在需要的文件中都被声明或定义一次,不仅浪费而且没法跨文件支持

@babel/plugin-transform-runtime 提供了一个沙盒环境,使用一些高版本 js 特性时会指向到 corejs,没有污染全局,但是因为没有在 prototype 上做 polyfill,一些高版本 js 的实例方法就没法使用了,比如:Array.prototype.includes 。

@babel/plugin-transform-runtime 让所有的 helper 函数都指向 @babel/runtime 组件,这样节省空间还能跨文件支持,方便统一管理。这也就要求 @babel/runtime 需要预先安装。

配置

在 .babelrc 配置文件里,带着默认参数的配置

{
  "plugins": [
    [
      "@babel/plugin-transform-runtime",
      {
        "absoluteRuntime": false,
        "corejs": false,
        "helpers": true,
        "regenerator": true,
        "useESModules": false
      }
    ]
  ]
}

corejs

从 "corejs": false 这个默认参数可以看出,@babel/plugin-transform-runtime 假定所有的 polyfill 需要用户自己提供:

image.png

图片来源:github.com/babel/babel…

总结下:

  • 配置 corejs 为 3,需要预先安装 @babel/runtime-corejs3
  • 配置 corejs 为 2,需要预先安装 @babel/runtime-corejs2
  • 配置 corejs 为 false,需要预先安装 @babel/runtime

absoluteRuntime

Babel 默认会从 node_modules  加载已经配置安装的 @babel/runtime 某个版本。absoluteRuntime 参数就是修改这个默认行为的,可以具体指定从哪里加载相应的 @babel/runtime。

其他配置项的解释参见:babeljs.io/docs/en/bab…