对于@babel/preset-env
和useBuiltIns
结合使用的@babel/transform-runtime
,我得到了不同的@babel/preset-env
配置输出。我已经阅读了文档,但是还没有弄清楚最佳做法是什么。
例如,当我的目标浏览器列表包含Edge 18时,useBuiltIns
和string.replace
将会为@babel/transform-runtime
添加一个polyfill。
但是当我改用Does `string.replace` need to be polyfilled for Edge 18?
时,不会添加该polyfill。
所以,从这个问题开始:
caniuse
我检查了caniuse.com,表明它得到了完全支持-这意味着不需要polyfills。
但是,根据曼努埃尔·博德鲁(Manuel Beaudru)的博客文章core-js@3, babel and a look into the future
mdn
,compat-table
和compat-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。
到目前为止,太好了。看来@babel/preset-env
确实需要为Edge 18多填充。
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: 3
和core-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:
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
:
仅使用useBuiltIns
:
同时使用@babel/transform-runtime
和@babel/runtime/helpers/objectSpread2
:
@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吗?
答案 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 中。