对@babel/preset-env (使用 Browserslist 集成)的 useBuiltIns 选项感到困惑

我正在做一个网络项目,使用 Babel 7和 Webpack 4。我以前从来没有用过巴别塔,有些地方我真的看不懂。基于 文件我正在使用 @babel/preset-env,因为它似乎是推荐的方式(特别是对于初学者)。也通过我的 .browserslistrc文件使用 Browserslist 集成。

Webpack 编译得很好(babel-loader版本 8.0.2) ,我没有错误,但我对这个 useBuiltIns: "entry" 这里提到的选项polyfill系统是如何在 Babel 工作感到困惑。

. babelrc.js

module.exports = {
presets: [
['@babel/preset-env', {
"useBuiltIns": "entry" // do I need this?
}]
],
plugins: [
'@babel/plugin-syntax-dynamic-import'
]
};

。浏览器
给你复制(认为合理,因为我的项目正在使用 Bootstrap)。

>= 1%
last 1 major version
not dead
Chrome >= 45
Firefox >= 38
Edge >= 12
Explorer >= 10
iOS >= 9
Safari >= 9
Android >= 4.4
Opera >= 30

所以我的问题是:

1)我是否需要使用 useBuiltIns: "entry"选项?

2)我是否需要安装 @babel/polyfill软件包并以 require("@babel/polyfill");开始我的 vendors.js

3)如果我两个都省略了呢?

如果我做1和2,我的 vendors.js长到 411 KB
如果两个都省略,那就是 341 KB
在生产完成之后。

我认为 @babel/preset-env处理所有的重写和填充默认没有任何额外的 import/require需要在我这边..。

谢谢!

编辑

Babel 的团队刚刚基于一些 GitHub 问题(包括我的问题)发布了 更新@babel/polyfill的文件,抱怨文档不清晰/误导。现在怎么用已经很明显了。(... 在那之后,我最初的问题似乎很愚蠢:)

34968 次浏览

1) Do I need to use that useBuiltIns: "entry" option?

Yes, according to babel docs:

"This option enables a new plugin that replaces the statement import "@babel/polyfill" or require("@babel/polyfill") with individual requires for @babel/polyfill based on environment" - Basically, includes all needed polyfills (when you have @babel/polyfill installed when needed).

2) Do I need to install @babel/polyfill package and start my vendors.js with require("@babel/polyfill"); ?

You do need to install @babel/polyfill, it does not come by default on babel. You have to include that on your entrypoint or add an import at the top of your entrypoint.

3) What if I omit both?

You won't have polyfills.

1) Do I need to use that useBuiltIns: "entry" option?

Yes, if you want to include polyfills based on your target environment.

TL;DR

There're basically 3 options for useBuiltIns:

"entry": when using this option, @babel/preset-env replaces direct imports of core-js to imports of only the specific modules required for a target environment.

That means you need to add

import "core-js/stable";
import "regenerator-runtime/runtime";

to your entry point and these lines will be replaced by only required polyfills. When targeting chrome 72, it will be transformed by @babel/preset-env to

import "core-js/modules/es.array.unscopables.flat";
import "core-js/modules/es.array.unscopables.flat-map";
import "core-js/modules/es.object.from-entries";
import "core-js/modules/web.immediate";

"usage": in this case polyfills will be added automatically when the usage of some feature is unsupported in target environment. So:

const set = new Set([1, 2, 3]);
[1, 2, 3].includes(2);

in browsers like ie11 will be replaced with

import "core-js/modules/es.array.includes";
import "core-js/modules/es.array.iterator";
import "core-js/modules/es.object.to-string";
import "core-js/modules/es.set";


const set = new Set([1, 2, 3]);
[1, 2, 3].includes(2);

In case target browser is latest chrome, no transformations will apply.

That's personally my chosen weapon as there's no need to include anything (core-js or regenerator) in source code as only required polyfills will be added automatically based on target environment set in browserlist.


false: that's the default value when no polyfills are added automatically.


2) Do I need to install @babel/polyfill package and start my vendors.js with require("@babel/polyfill"); ?

Yes for environment prior to babel v7.4 and core-js v3.

TL;DR

No. Starting from babel v7.4 and core-js v3 (which is used for polyfilling under the hood) @babel/preset-env will add the polyfills only when it know which of them required and in the recommended order.

Moreover @babel/polyfill is considered as deprecated in favor of separate core-js and regenerator-runtime inclusions.

So using of useBuiltIns with options other than false should solve the issue.

Don't forget to add core-js as a dependency to your project and set its version in @babel/preset-env under corejs property.


3) What if I omit both?

As @PlayMa256 already answered, there will be no polyfills.


More detailed and whole info con be found at core-js creator's page

Also please feel free to play with babel sandbox