Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Clarify docs about env "useBuiltIns" behavior and common uses. #2425

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
129 changes: 74 additions & 55 deletions docs/preset-env.md
Expand Up @@ -264,18 +264,85 @@ This option is useful for "blacklisting" a transform like `@babel/plugin-transfo

`"usage"` | `"entry"` | `false`, defaults to `false`.

This option configures how `@babel/preset-env` handles polyfills.
This option configures how `@babel/preset-env` handles polyfills and whether optimizations are applied to only include polyfills that are needed.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about something like:

Suggested change
This option configures how `@babel/preset-env` handles polyfills and whether optimizations are applied to only include polyfills that are needed.
This option configures `@babel/preset-env` to only include the polyfills needed by your target environment(s). This can either include all polyfills needed to mimic a ES2020 environment (`entry`), or only include polyfills as they are needed/used in each file (`usage`).

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Riffing on that a bit more, how about this? I dropped mention of ES2020 because that will become outdated eventually.

Suggested change
This option configures how `@babel/preset-env` handles polyfills and whether optimizations are applied to only include polyfills that are needed.
This option configures `@babel/preset-env` to only include the polyfills needed by your target environment(s) to mimic the latest JS-spec environment. Options are to include polyfills as they are needed/used in each file (`usage`) or include polyfills at the entrypoint to your application (`entry`).

Given the nuance you mention, I'm not exactly clear on what are the pros/cons of each? If usage wouldn't help people in the case about node_modules you mentioned above, is there a reason people wouldn't always just use entry? If I understand that aspect more, then I think we could get a better synopsis out to users.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are certainly people who do compile their node_modules (or if you're sure that your deps don't need to be polyfilled) to get the full benefit of usage, it's just a caveat that people may not be aware of when they're setting up Babel for their project.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That totally makes sense. I'm just trying to understand, when you say "the full benefit of usage", what is that benefit? Are there benefits of usage over entry? I think that would be good to showcase.


When either the `usage` or `entry` options are used, `@babel/preset-env` will add direct references to `core-js` modules as bare imports (or requires). This means `core-js` will be resolved relative to the file itself and needs to be accessible.

Since `@babel/polyfill` was deprecated in 7.4.0, we recommend directly adding `core-js` and setting the version via the [`corejs`](#corejs) option.
When specifying polyfilling behavior, you will want to include `core-js` and probably `regenerator-runtime` dependencies:

```sh
npm install core-js@3 --save
npm install --save core-js regenerator-runtime
```

You'll also need to set the core-js version via the [`corejs`](#corejs) option:

```json
{
"presets": [
[
"@babel/preset-env",
{
"corejs": 3
}
]
]
}
```

# or
Generally, `"usage"` meets the needs of most users by only including the polyfills that are needed.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This might be a tricky recommendation for users who have dependencies in node_modules that rely on certain built-ins being available that aren't run through Babel.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I hadn't even considered that. Sounds like a nuance worth mentioning, I'll include that...


npm install core-js@2 --save
#### `useBuiltIns: 'usage'`

Adds specific imports for polyfills when they are used in each file. We take advantage of the fact that a bundler will load the same polyfill only once.

You do not need to provide "entry level" import statements, as with the `"entry"` option.

```js
// nope
import 'core-js';
import 'regenerator-runtime/runtime';
```

**In**

a.js

```js
var a = new Promise();
```

b.js

```js
var b = new Map();
```

**Out (if environment doesn't support it)**

a.js

```js
import "core-js/modules/es.promise";
var a = new Promise();
```

b.js

```js
import "core-js/modules/es.map";
var b = new Map();
```

**Out (if environment supports it)**

a.js

```js
var a = new Promise();
```

b.js

```js
var b = new Map();
```

#### `useBuiltIns: 'entry'`
Expand Down Expand Up @@ -336,54 +403,6 @@ You can read [core-js](https://github.com/zloirock/core-js)'s documentation for
> NOTE: When using `core-js@2` (either explicitly using the [`corejs: 2`](#corejs) option or implicitly), `@babel/preset-env` will also transform imports and requires of `@babel/polyfill`.
> This behavior is deprecated because it isn't possible to use `@babel/polyfill` with different `core-js` versions.

#### `useBuiltIns: 'usage'`

Adds specific imports for polyfills when they are used in each file. We take advantage of the fact that a bundler will load the same polyfill only once.

**In**

a.js

```js
var a = new Promise();
```

b.js

```js
var b = new Map();
```

**Out (if environment doesn't support it)**

a.js

```js
import "core-js/modules/es.promise";
var a = new Promise();
```

b.js

```js
import "core-js/modules/es.map";
var b = new Map();
```

**Out (if environment supports it)**

a.js

```js
var a = new Promise();
```

b.js

```js
var b = new Map();
```

#### `useBuiltIns: false`

Don't add polyfills automatically per file, and don't transform `import "core-js"` or `import "@babel/polyfill"` to individual polyfills.
Expand Down