babel-polyfill 与 babel-runtime

Babel 默认只转换新的JavaScript语法,而不转换新的API。 例如,Iterator、Generator、Set、Maps、Proxy、Reflect、Symbol、Promise 等全局对象,以及一些定义在全局对象上的方法(比如 Object.assign)都不会转译。 如果想使用这些新的对象和方法,则需要为当前环境提供一个 polyfill。

从 Babel 7.4.0 开始, 已经不建议使用 @babel/polyfill 库了,建议直接引入 core-js/stable 和 regenerator-runtime/runtime:(useBuiltIns选项已经移除,成为默认设置)
import "core-js/stable";
import "regenerator-runtime/runtime";

core-js 标准库

这是所有 Babel polyfill 方案都需要依赖的开源库zloirock/core-js,它提供了 ES5、ES6 的 polyfills,包括 promises 、symbolscollections、iterators、typed arraysECMAScript 7+ proposalssetImmediate 等等。

如果使用了 babel-polyfill 或者 babel-runtime、babel-plugin-transform-runtime,你就间接的引入了 core-js 标准库和 regenerator-runtime 运行时库(babel-runtime 引入)。

babel-polyfill

目前最常用的配合 Babel 一起使用的 polyfill 是 babel-polyfill,它会”加载整个polyfill库”,针对编译的代码中新的API进行处理,并且在代码中插入一些帮助函数。

在webpack配置文件中的入口或者公共模块中加入’babel-polyfill’即可。
npm install --save @babel/polyfill
import "@babel/polyfill";

babel-polyfill 可以定制,在.babelrc 文件中 babel-preset-env 开启 useBuiltIns

useBuiltIns: 'entry'

babel-polyfill解决了Babel不转换新API的问题,但是直接在代码中插入帮助函数,会导致污染了全局环境,并且不同的代码文件中包含重复的代码,导致编译后的代码体积变大。 

Babel为了解决这个问题,提供了单独的包babel-runtime用以提供编译模块的工具函数, 启用插件babel-plugin-transform-runtime后,Babel就会使用babel-runtime下的工具函数。

babel-runtime

babel-runtime 是由 Babel 提供的 polyfill 库,它本身就是由 core-js 与 regenerator-runtime 库组成。

babel-plugin-transform-runtime 插件

这个插件让 Babel 发现代码中使用到 Symbol、Promise、Map 等新类型时,自动且按需进行 polyfill,因为是“自动”所以非常受大家的欢迎。

需要你在 .babelrc 或 Babel 编译选项中将该插件添加到 plugins 中,插件只会 polyfill 你用到的类或方法。
使用 babel-runtime 需要额外安装 babel-runtime 和 babel-plugin-transform-runtime 依赖包, 然后在.babelrc 配置文件中启用 transform-runtime, 代码如下:
npm install --save @babel/runtime
npm install --save-dev @babel/plugin-transform-runtime
{
  "plugins": [
    [
      "@babel/plugin-transform-runtime",
      {
        "absoluteRuntime": false,
        "corejs": false,
        "helpers": true,
        "regenerator": true,
        "useESModules": false,
        "version": "7.0.0-beta.0"
      }
    ]
  ]
}

在官网中,Babel 提醒大家如果正在开发一个 library 的话,建议使用这种方案,因为没有全局变量和 prototype 污染。

因此,babel-plugin-transform-runtime 这个插件更适合于开发类库(library)时去使用,而不适合直接用在独立的前端工程中。另外,它可以按需 polyfill,所以从一定程度上控制了 polyfill 文件的大小。

V7开始推荐的预置项包括:(移除了Stage-X 版本)

presets: [
    require("@babel/preset-env"),
],

参考:

https://babeljs.io/docs/en/babel-plugin-transform-runtime

https://zhuanlan.zhihu.com/p/29058936

https://www.jianshu.com/p/73ba084795ce