如何添加|如何添加 babel polyfill?

由于 Babel 7.4 之后不再推荐使用 @babel/polyfill,而 @babel/preset-envplugin-transform-runtime 二者都可以设置 corejs 来处理 polyfill

@babel/polyfill废弃的主要原因有:
  • 此包仅仅是引入了 stable core-js 和 regenerator-runtime/runtime,其中后者可以使用插件 @babel/plugin-transform-regenerator 代替。
  • 此包不能从core-js@2 平滑过渡到 core-js@3。
Babel 简介 简单来说,Babel 是一个编译器,主要用于将采用 ECMAScript 2015+ 语法编写的代码转换为向后兼容的 JavaScript 语法,以便能够运行在新旧版本的浏览器等各个环境中。而 Babel 代码转换功能以 plugin 的方式实现,plugin 就是小型的 JavaScript 程序。
preset可以被看作是一组 Babel 插件或 options 配置的可共享模块。
  • plugins 在 presets 前运行;
  • plugins 从前往后顺序执行;
  • presets 根据排列顺序倒序执行;
babel 主要实现的两个功能:
  1. 转换新语法。将新版 js 语法用旧版语法实现,从而在对应环境中运行,比如箭头函数;
  2. 转换新 API。为旧版运行时打补丁(也被称为polyfill),从而使用在新版 js 中定义但在旧版运行时提供的功能,包括三类:
    • 新定义的内置对象,例如 Promise
    • 原有内置对象新添加的静态方法,例如 Array.from
    • 原有内置对象新添加的实例方法,例如 Array.prototype.includes
preset-env preset-env 既可以转换新语法,也可以通过配置转换新的 APIpreset-envpolyfill 会污染全局环境。
target
这个字段可以填写 browserslist 的查询字符串,官方推荐使用 .browserslistrc 文件去指明编译的 target,这个配置文件还可以和autoprefixerstylelint等工具一起共享配置。所以不推荐在.babelrcpreset-env配置中直接使用targets进行配置。
如果需要单独在这里配置targets的话,preset-env中指明ignoreBrowserslistConfigtrue则忽略.browserslistrc的配置项。
useBuiltIns
是否使用其polyfill功能(全局环境的core-js)。有三个值:
  • false:默认值。在不主动import的情况下不使用preset-env来实现polyfills,只使用其默认的语法转换功能。如果使用默认值false,则应该避免在入口文件引入polyfill,使得打包体积过大。
  • entry:需要手动在入口处引入 polyfill,根据浏览器目标环境(targets)的配置,引入全部浏览器暂未支持的 polyfill模块,无论在项目中是否使用到。
    import "core-js/proposals/string-replace-all"

  • usage: 不需要手动在入口文件引入polyfillBabel将会根据代码使用情况自动注入polyfill,如此一来在打包的时候将会相对地减少打包体积。
corejs
配置core-js,默认值"2.0"。此选项仅在与 useBuiltIns: usageuseBuiltIns: entry 一起使用时有效。
core-js: JavaScript 的模块化标准库,包含 PromiseSymbolIterator和许多其他的特性,它可以让你仅加载必需的功能。
  • version: 【string】版本号;
  • proposals: 【boolean】是否实现提案中的特性;
// .babelrc { "presets": [ [ "@babel/preset-env", { "targets": { "chrome": "80" // 推荐使用 .browserslistrc }, "useBuiltIns": "usage", "corejs": { "version": 3, // 2 和 3 版本都需要手动安装库:yarn add core-js@3 "proposals": false } } ] ] }

plugin-transform-runtime plugin-transform-runtime 主要做了三件事:
  • 当开发者使用异步或生成器的时候,自动引入@babel/runtime/regenerator,开发者不必在入口文件做额外引入;
  • 动态引入 polyfill,提供沙盒环境,避免全局环境的污染;
    如果直接导入 core-js 或 @babel/polyfill 以及它提供的 Promise、Set 和 Map 等内置组件,这些都会污染全局。虽然这不影响应用程序或命令行工具,但如果代码是要发布给其他人使用的库,或者无法准确控制代码将运行的环境,则会出现问题。
  • 所有 helpers 帮助模块都将引用模块 @babel/runtime,以避免编译输出中的重复,减小打包体积;
corejs
配置值:false, 2, 或者 { version: number, proposals: boolean },默认值 false。
corejs 安装建议
false npm install --save @babel/runtime
2 npm install --save @babel/runtime-corejs2
3 npm install --save @babel/runtime-corejs3
helpers
配置值 boolean 类型,默认值 true。
是否用对 moduleName 的调用替换内联 Babel 帮助程序(classCallCheck、extends等)。
regenerator
配置值 boolean 类型,默认值 true。
是否将生成器函数转换为使用不污染全局范围的再生器运行时。
useESModules
配置值 boolean 类型,默认值 false。
启用后,转换将使用帮助程序,而不是@babel/plugin-transform-modules-commonjs。这允许在 webpack 等模块系统中进行较小的构建,因为它不需要保留 commonjs 语义。
使用场景分析 @babel/preset-envplugin-transform-runtime 二者都可以设置使用 corejs 来处理polyfill,二者各有使用场景,在项目开发和类库开发的时候可以使用不同的配置。
不要同时为二者配置 core-js,以免产生复杂的不良后果。
项目开发
useBuiltIns 使用 usageplugin-transform-runtime 只使用其移除内联复用的辅助函数的特性,减小打包体积。
{ "presets": [ [ "@babel/preset-env", { "useBuiltIns": "usage", "corejs": { "version": 3, "proposals": false } } ] ], "plugins": [ [ "@babel/plugin-transform-runtime", { "corejs": false } ] ] }

类库开发
【如何添加|如何添加 babel polyfill?】类库开发尽量不使用污染全局环境的 polyfill,因此 @babel/preset-env 只发挥语法转换的功能, polyfillplugin-transform-runtime 来处理,推荐使用 core-js@3,并且不使用未进入规范的特性。
{ "presets": ["@babel/preset-env"], "plugins": [ [ "@babel/plugin-transform-runtime", { "corejs": { "version": 3, "proposals": false }, "useESModules": true } ] ] }

    推荐阅读