“ @ babel / preset-env” +“ useBuiltIns” +“ @ babel / runtime” +“ browserslistrc”

时间:2020-08-03 14:42:08

标签: javascript babeljs babel-preset-env

对于@babel/preset-envuseBuiltIns结合使用的@babel/transform-runtime,我得到了不同的@babel/preset-env配置输出。我已经阅读了文档,但是还没有弄清楚最佳做法是什么。

例如,当我的目标浏览器列表包含Edge 18时,useBuiltInsstring.replace将会为@babel/transform-runtime添加一个polyfill。

但是当我改用Does `string.replace` need to be polyfilled for Edge 18? 时,不会添加该polyfill。


所以,从这个问题开始:

caniuse

mdncompat-tablecompat-table是很好的教育资源,但 并不是真正要用作开发人员工具的数据源: 只有core-js-compat包含一组与ES相关的数据,并且 由@ babel / preset-env使用,但有一些限制

进一步:

由于这个原因,我创建了core-js@3软件包: 有关针对不同目标的core-js模块的必要性的数据 引擎。使用@babel/preset-env时,compat-table.将使用新的 而不是core-js-compat

因此,我将目标浏览器传递给了string.replace,它输出了所需的所有填充。正如您在下图中所看到的,需要多填充很多字符串方法,主要是为了支持Edge 18。

enter image description here

到目前为止,太好了。看来@babel/preset-env 确实需要为Edge 18多填充。


Babel配置

第一种方法:useBuiltIns: 'usage'useBuiltIns: 'usage'

当我使用core-js// babel.config.js presets: [ [ '@babel/preset-env', { debug: false, bugfixes: true, useBuiltIns: 'usage', corejs: { version: "3.6", proposals: true } } ], '@babel/preset-flow', '@babel/preset-react' ], 引入按文件填充时:

debug: true

PriceColumn.js时,Babel说它将在我的// Console output [/price-column/PriceColumn.js] Added following core-js polyfills: es.string.replace { "edge":"17", "firefox":"71", "ios":"12", "safari":"12" } es.string.split { "edge":"17" } web.dom-collections.iterator { "edge":"17", "ios":"12", "safari":"12" } 文件中添加以下polyfill:

es.string.replace

区别在于它说edge: 17是针对edge: 18而不是core-js-compat,正如我们在上面PriceColumn.js的输出中看到的那样-可能是我做的,但目前还可以。

Babel添加到已转换的// PriceColumn.js "use strict"; require("core-js/modules/es.string.replace"); require("core-js/modules/es.string.split"); require("core-js/modules/web.dom-collections.iterator"); Object.defineProperty(exports, "__esModule", { value: true }); exports.default = void 0; 文件顶部的附加内容:

@babel/runtime

再次,到目前为止一切顺利。


第二种方法:@babel/transform-runtime@babel/runtime

根据core-js文档:

corejs: 3core-js-pure选项可简化使用 core-js。它会自动取代现代功能的使用 从JS标准库到从useBuiltIns版本导入 没有全球名称空间污染

听起来很棒-试试吧!

注释@babel/transform-runtime并添加// babel.config.js presets: [ [ '@babel/preset-env', { debug: true, // bugfixes: true, // useBuiltIns: 'usage', // corejs: { version: '3.6', proposals: true } } ], '@babel/preset-flow', '@babel/preset-react' ], plugins: [ [ '@babel/transform-runtime', { corejs: { version: 3, proposals: true }, version: '^7.8.3' } ] ], 插件配置:

Using polyfills: No polyfills were added, since the `useBuiltIns` option was not set.

在控制台输出中,我看到:

// PriceColumn.js

"use strict";

var _interopRequireDefault = require("@babel/runtime-corejs3/helpers/interopRequireDefault");

var _Object$defineProperty = require("@babel/runtime-corejs3/core-js/object/define-property");

_Object$defineProperty(exports, "__esModule", {
  value: true
});

exports.default = void 0;

var _objectSpread2 = _interopRequireDefault(require("@babel/runtime-corejs3/helpers/objectSpread2"));

var _map = _interopRequireDefault(require("@babel/runtime-corejs3/core-js/instance/map"));

检查添加到文件顶部的内容:

helpers

因此,添加了不同的es.string.*-但没有corejs填充的迹象。不再需要它们了吗?他们已经被“帮助者”带来了吗?看起来对象散布和数组映射似乎与polyfilling字符串实例方法无关,所以我认为不是。


最后

我最后的尝试是结合两种方法-并遵循recommendations

enter image description here

a)将@babel/preset-env设置为// babel.config.js presets: [ [ '@babel/preset-env', { debug: true, // bugfixes: true, useBuiltIns: 'usage', corejs: { version: '3.6', proposals: true } } ], '@babel/preset-flow', '@babel/preset-react' ], plugins: [ [ '@babel/transform-runtime', { // corejs: { version: 3, proposals: true }, version: '^7.8.3' } ] ]

// PriceColumn.js

"use strict";

var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");

require("core-js/modules/es.string.replace");

require("core-js/modules/es.string.split");

require("core-js/modules/web.dom-collections.iterator");

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.default = void 0;

var _objectSpread2 = _interopRequireDefault(require("@babel/runtime/helpers/objectSpread2"));

这是输出:

corejs

b)为@babel/transform-runtime设置useBuiltIns

  • 与第二种方法相同(请参见上文)

比较不同方法的输出

仅使用@babel/runtime-transform

  • 引入所需的字符串polyfill,但会污染全局名称空间。

仅使用useBuiltIns

  • 不引入任何字符串polyfill,而是引入其他帮助器/ polyfill ??,用于数组映射和对象散布

同时使用@babel/transform-runtime@babel/runtime/helpers/objectSpread2

  • 引入所需的字符串polyfill,但会污染全局名称空间。
  • 还引入了对象分布的polyfill(但没有引入Array map polyfill)
  • @babel/runtime-corejs3/helpers/objectSpread2而不是@babel/preset-env导入(运行时vs运行时-corejs3)-可能是未引入数组映射polyfill的原因?)

问题

其中哪种方法(如果有)是正确的?

我猜useBuiltIns@babel/transform-runtime是最好的,因为它带来了polyfills。

污染全局名称空间有哪些弊端?这仅是图书馆的问题吗?

结合@babel-preset-env,我们还获得了用于对象传播的polyfill(尽管corejs: { version: '3.6', proposals: true }具有@babel/transform-runtime应该可以进行polyfill提案,所以我不确定为什么不这样做)无需使用{{1}}插件就可以进入那里

我们需要Array#map polyfill吗?

1 个答案:

答案 0 :(得分:6)

https://www.jmarkoski.com/understanding-babel-preset-env-and-transform-runtime推荐:

App:如果您正在编写应用程序,请在应用程序顶部使用 import 'core-js 并将 useBuiltIns 设置为 entry 和 @babel/transform-runtime 仅用于帮助程序 (@babel/运行时作为依赖)。这样你污染了全球环境,但你不在乎,这是你的应用程序。您将受益于别名为 @babel/runtime 的助手和包含在您的应用程序顶部的 polyfill。通过这种方式,您也不需要处理 node_modules(除非依赖项使用必须转换的语法),因为如果某些依赖项使用了需要 polyfill 的功能,那么您已经在应用程序的顶部包含了该 polyfill。< /p>

:如果您正在编写库,请仅使用带有 corejs 选项的 @babel/transform-runtime 加上 @babel/runtime-corejs3 作为依赖项,并使用 @babel/preset-env 进行语法转换使用 useBuiltIns: false。此外,我会从 node_modules 转译我将使用的包。为此,您需要设置 absoluteRuntime 选项 (https://babeljs.io/docs/en/babel-plugin-transform-runtime#absoluteruntime) 以从单个位置解决运行时依赖项,因为 @babel/transform-runtime 直接从 @babel/runtime-corejs3 导入,但这仅适用于 @ babel/runtime-corejs3 位于正在编译的文件的 node_modules 中。