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

Update docs for core-js 3 #1987

Merged
merged 6 commits into from
Apr 9, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 27 additions & 31 deletions docs/plugin-transform-runtime.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ sidebar_label: transform-runtime

A plugin that enables the re-use of Babel's injected helper code to save on codesize.

> NOTE: Instance methods such as `"foobar".includes("foo")` will not work since that would require modification of existing built-ins (you can use [`@babel/polyfill`](polyfill.md) for that).
> NOTE: Instance methods such as `"foobar".includes("foo")` will only work with `core-js@3`. If you need to polyfill them, you can directly import `"core-js"` or use `@babel/preset-env`'s `useBuiltIns` option.

## Installation

Expand All @@ -30,7 +30,7 @@ Babel uses very small helpers for common functions such as `_extend`. By default

This is where the `@babel/plugin-transform-runtime` plugin comes in: all of the helpers will reference the module `@babel/runtime` to avoid duplication across your compiled output. The runtime will be compiled into your build.

Another purpose of this transformer is to create a sandboxed environment for your code. If you use [@babel/polyfill](polyfill.md) and the built-ins it provides such as `Promise`, `Set` and `Map`, those will pollute the global scope. While this might be ok for an app or a command line tool, it becomes a problem if your code is a library which you intend to publish for others to use or if you can't exactly control the environment in which your code will run.
Another purpose of this transformer is to create a sandboxed environment for your code. If you directly import [core-js](https://github.com/zloirock/core-js) or [@babel/polyfill](polyfill.md) and the built-ins it provides such as `Promise`, `Set` and `Map`, those will pollute the global scope. While this might be ok for an app or a command line tool, it becomes a problem if your code is a library which you intend to publish for others to use or if you can't exactly control the environment in which your code will run.

The transformer will alias these built-ins to `core-js` so you can use them seamlessly without having to require the polyfill.

Expand Down Expand Up @@ -88,17 +88,22 @@ require("@babel/core").transform("code", {

### `corejs`

`boolean` or `number` , defaults to `false`.
`false`, `2`, `3` or `{ version: 2 | 3, proposals: boolean }`, defaults to `false`.
Copy link
Member

Choose a reason for hiding this comment

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

At the top of this page a note that runtime does not support instance methods, now it's not correct.

Too many links to deprecated @babel/polyfill as a global alternative.

This page does not contain a link to core-js documentation. However, users should know what they are using. I think that we need to add it at least on the first core-js entry.

Copy link

@radum radum Mar 27, 2019

Choose a reason for hiding this comment

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

As part of this doc part I would also add a bit more clarity around how corejs works in conjunction with the corejs option from @babel/preset-env.

If both options are set to something other than false then the corejs imports will be duplicated. One for preset-env and one for transform-runtime.

A bit more clarity that if you use preset-env with corejs option you should not use the same for transform runtime will help some developer understand what is going on.

This relates to some confusion from this issue #9728.

The same info could be added to the preset-env doc also for reference.


e.g. `['@babel/plugin-transform-runtime', { corejs: 2 }],`
e.g. `['@babel/plugin-transform-runtime', { corejs: 3 }],`

Specifying a number will rewrite the helpers that need polyfillable APIs to reference `core-js` instead.
Specifying a number will rewrite the helpers that need polyfillable APIs to reference helpers from that (major) version of `core-js` instead
Please note that `corejs: 2` only supports global variables (e.g. `Promise`) and static properties (e.g. `Array.from`), while `corejs: 3` also supports instance properties (e.g. `[].includes`).

This requires changing the dependency used to be [`@babel/runtime-corejs2`](runtime-corejs2.md) instead of `@babel/runtime`.
By default, `@babel/plugin-transform-runtime` doesn't polyfill proposals. If you are using `corejs: 3`, you can opt into this by enabling using the `proposals: true` option.

```sh
npm install --save @babel/runtime-corejs2
```
This option requires changing the dependency used to provide the necessary runtime helpers:
Copy link
Member

@existentialism existentialism Mar 14, 2019

Choose a reason for hiding this comment

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

Think it's too verbose to do? (On the fence, ignore if you think it's too much)

corejs option Install
false npm install --save @babel/runtime
2 npm install --save @babel/runtime-corejs2
3 npm install --save @babel/runtime-corejs3

Copy link
Member Author

Choose a reason for hiding this comment

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

Yeah it's better: people will only need to copy-paste


| `corejs` option | Install command |
|-----------------|---------------------------------------------|
| `false` | `npm install --save @babel/runtime` |
| `2` | `npm install --save @babel/runtime-corejs2` |
| `3` | `npm install --save @babel/runtime-corejs3` |

### `helpers`

Expand Down Expand Up @@ -247,43 +252,34 @@ The plugin transforms the following:
```javascript
var sym = Symbol();

var promise = new Promise();
var promise = Promise.resolve();

var check = arr.includes("yeah!");

console.log(arr[Symbol.iterator]());
```

into the following:

```javascript
"use strict";

var _getIterator2 = require("@babel/runtime-corejs2/core-js/get-iterator");

var _getIterator3 = _interopRequireDefault(_getIterator2);
import _getIterator from "@babel/runtime-corejs3/core-js/get-iterator";
import _includesInstanceProperty from "@babel/runtime-corejs3/core-js-stable/instance/includes";
import _Promise from "@babel/runtime-corejs3/core-js-stable/promise";
import _Symbol from "@babel/runtime-corejs3/core-js-stable/symbol";

var _promise = require("@babel/runtime-corejs2/core-js/promise");

var _promise2 = _interopRequireDefault(_promise);

var _symbol = require("@babel/runtime-corejs2/core-js/symbol");

var _symbol2 = _interopRequireDefault(_symbol);

function _interopRequireDefault(obj) {
return obj && obj.__esModule ? obj : { default: obj };
}
var sym = _Symbol();

var sym = (0, _symbol2.default)();
var promise = _Promise.resolve();

var promise = new _promise2.default();
var check = _includesInstanceProperty(arr).call(arr, "yeah!");

console.log((0, _getIterator3.default)(arr));
console.log(_getIterator(arr));
```

This means is that you can seamlessly use these native built-ins and static methods
This means is that you can seamlessly use these native built-ins and methods
without worrying about where they come from.

**NOTE:** Instance methods such as `"foobar".includes("foo")` will **not** work.
**NOTE:** Instance methods such as `"foobar".includes("foo")` will only work when using `corejs: 3`.

### Helper aliasing

Expand Down
6 changes: 6 additions & 0 deletions docs/polyfill.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,12 @@ title: @babel/polyfill
sidebar_label: polyfill
---

> 🚨 As of Babel 7.4.0, this package has been deprecated in favor of directly including `core-js/stable` (to polyfill ECMAScript features) and `regenerator-runtime/runtime` (needed to use transpiled generator functions):
> ```js
> import "core-js/stable";
> import "regenerator-runtime/runtime";
> ```

Babel includes a [polyfill](<https://en.wikipedia.org/wiki/Polyfill_(programming)>) that includes a custom [regenerator runtime](https://github.com/facebook/regenerator/blob/master/packages/regenerator-runtime/runtime.js) and [core-js](https://github.com/zloirock/core-js).

This will emulate a full ES2015+ environment (no < Stage 4 proposals) and is intended to be used in an application rather than a library/tool.
Expand Down
88 changes: 67 additions & 21 deletions docs/preset-env.md
Original file line number Diff line number Diff line change
Expand Up @@ -197,14 +197,14 @@ Valid options include any:

- [Babel plugins](https://github.com/babel/babel/blob/master/packages/babel-preset-env/data/plugin-features.js) - both with (`@babel/plugin-transform-spread`) and without prefix (`plugin-transform-spread`) are supported.

- [Built-ins](https://github.com/babel/babel/blob/master/packages/babel-preset-env/data/built-in-features.js), such as `es6.map`, `es6.set`, or `es6.object.assign`.
- Built-ins (both for [core-js@2](https://github.com/babel/babel/blob/master/packages/babel-preset-env/src/polyfills/corejs2/built-in-definitions.js) and [core-js@3]([https://github.com/babel/babel/blob/master/packages/babel-preset-env/src/polyfills/corejs3/built-in-definitions.js](https://github.com/babel/babel/blob/master/packages/babel-preset-env/src/polyfills/corejs3/built-in-definitions.js)))), such as `es.map`, `es.set`, or `es.object.assign`.

Plugin names can be fully or partially specified (or using `RegExp`).

Acceptable inputs:

- Full name (`string`): `"es6.math.sign"`
- Partial name (`string`): `"es6.math.*"` (resolves to all plugins with `es6.math` prefix)
- Full name (`string`): `"es.math.sign"`
- Partial name (`string`): `"es.math.*"` (resolves to all plugins with `es.math` prefix)
- `RegExp` Object: `/^transform-.*$/` or `new RegExp("^transform-modules-.*")`

Note that the above `.` is the `RegExp` equivalent to match any character, and not the actual `'.'` character. Also note that to match any character `.*` is used in `RegExp` as opposed to `*` in `glob` format.
Expand All @@ -229,38 +229,71 @@ This option is useful for "blacklisting" a transform like `@babel/plugin-transfo

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

> This option adds direct references to the `core-js` module as bare imports. Thus `core-js` will be resolved relative to the file itself and needs to be accessible. You may need to specify `core-js@2` as a top level dependency in your application if there isn't a `core-js` dependency or there are multiple versions.

This option configures how `@babel/preset-env` handles polyfills.

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.

Copy link
Member

Choose a reason for hiding this comment

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

The same as in runtime docs - I don't see any links to core-js documentation in this file.

Copy link
Member

Choose a reason for hiding this comment

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

Built-ins link in include should be updated.

Since `@babel/polyfill` was deprecated in 7.4.0, we recommend directly adding `core-js` and setting the version via the [`corejs`](#corejs) option.

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

# or

npm install core-js@2 --save
```

#### `useBuiltIns: 'entry'`

> NOTE: Only use `require("@babel/polyfill");` once in your whole app.
> Multiple imports or requires of `@babel/polyfill` will throw an error since it can cause global collisions and other issues that are hard to trace.
> We recommend creating a single entry file that only contains the `require` statement.
> NOTE: Only use `import "core-js";` and `import "regenerator-runtime/runtime";` once in your whole app.
Copy link
Member

Choose a reason for hiding this comment

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

I think we need to rework this section to note that while @babel/polyfill is deprecated, it still works?

> If you are using `@babel/polyfill`, it already includes both `core-js` and `regenerator-runtime`: importing it twice will throw an error.
> Multiple imports or requires of those packages might cause global collisions and other issues that are hard to trace.
> We recommend creating a single entry file that only contains the `import` statements.

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.
This option enables a new plugin that replaces the `import "core-js/stable";` and `import "regenerator-runtime/runtime"` statements (or `require("corejs")` and `require("regenerator-runtime/runtime")`) with individual requires to different `core-js` entry points based on environment.

```sh
npm install @babel/polyfill --save
**In**

```js
import "core-js";
```

**Out (different based on environment)**

```js
import "core-js/modules/es.string.pad-start";
import "core-js/modules/es.string.pad-end";
```

Importing `"core-js"` loads polyfills for every possible ECMAScript feature: what if you know that you only need some of them? When using `core-js@3`, `@babel/preset-env` is able to optimize every single `core-js` entrypoint and their combinations. For example, you might want to only polyfill array methods and new `Math` proposals:

**In**

```js
import "@babel/polyfill";
import "core-js/es/array";
import "core-js/proposals/math-extensions";
```

**Out (different based on environment)**

```js
import "core-js/modules/es7.string.pad-start";
import "core-js/modules/es7.string.pad-end";
import "core-js/modules/es.array.unscopables.flat";
import "core-js/modules/es.array.unscopables.flat-map";
import "core-js/modules/esnext.math.clamp";
import "core-js/modules/esnext.math.deg-per-rad";
import "core-js/modules/esnext.math.degrees";
import "core-js/modules/esnext.math.fscale";
import "core-js/modules/esnext.math.rad-per-deg";
import "core-js/modules/esnext.math.radians";
import "core-js/modules/esnext.math.scale";
```

This will also work for `core-js` directly (`import "core-js";` or `require('core-js');`)
You can read [core-js](https://github.com/zloirock/core-js)'s documentation for more information about the different entry points.

#### `useBuiltIns: 'usage'` (experimental)
> NOTE: When using `core-js@2` (either explicitly using the [`corejs: 2`](#corejs) option or implicitly), `@babel/preset-env` will also 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'`
Copy link
Member

Choose a reason for hiding this comment

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

As a sidenote, if we're going to remove the experimental tag here, we should enumerate all the caveats of using usage (e.g. includes doesn't work, etc) as there's lots of issues/confusion here.

Copy link
Member Author

Choose a reason for hiding this comment

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

Well, includes will work after the core-js 3 pr

Copy link
Member

Choose a reason for hiding this comment

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

Ah, I must have missed that.

Does it fix it for core-js 2 (didn't see that mentioned)? If not, it's even more reason for us to enumerate the caveats depending on the version of core-js being used?

Copy link
Member Author

@nicolo-ribaudo nicolo-ribaudo Mar 14, 2019

Choose a reason for hiding this comment

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

I think that we both confused @babel/preset-env with @babel/transform-runtime 😛 . Instance methods were already polyfilled when using core-js@2 repl

Input:

foo.includes;

Output:

require("core-js/modules/es7.array.includes");
require("core-js/modules/es6.string.includes");

foo.includes;

I don't know what caveats useBuiltIns: usage has, but if you point them out I can write them in the docs (or keep the "experimental" tag).

Copy link
Member

Choose a reason for hiding this comment

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

@nicolo-ribaudo with core-js@2, useBuiltIns: usage had really many limitations and bugs. With core-js@3 target a serious part of them was fixed and I think that we can remove experimental tag.

Copy link
Member

@zloirock zloirock Mar 14, 2019

Choose a reason for hiding this comment

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

Just some examples:

new Map() + ''; // => '[object Object] - `Object#toString` definition was broken
Object.getOwnPropertySymbols; // => undefined - this definition also was broken

import(something).then(...); // => Error  - `Promise` is not polyfilled in Webpack helpers

global.Set; // => undefined

something.finally;

// in another file
Promise.resolve().finally; // => most likely undefined because of incorrect polyfilling order

'values' in Object; // => false

and many other.

Copy link
Member

Choose a reason for hiding this comment

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

Sure, it's awesome that usage with core-js@3 is much improved over the previous version, but we need to communicate to users caveats and issues with with both versions as not everyone may have the freedom or luxury to upgrade immediately.

@nicolo-ribaudo I was referring to the the @babel/preset-env includes option not working with 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.

Expand All @@ -281,12 +314,12 @@ var b = new Map();
**Out (if environment doesn't support it)**

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

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

Expand All @@ -302,7 +335,19 @@ var b = new Map();

#### `useBuiltIns: false`

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

### `corejs`

`2`, `3` or `{ version: 2 | 3, proposals: boolean }`, defaults to `2`.

This option only has an effect when used alongside `useBuiltIns: usage` or `useBuiltIns: entry`, and ensures `@babel/preset-env` injects the correct imports for your `core-js` version.

By default, only polyfills for stable ECMAScript features are injected: if you want to polyfill them, you have three different options:
- when using `useBuiltIns: "entry"`, you can directly import a [proposal polyfill](https://github.com/zloirock/core-js/tree/master/packages/core-js/proposals): `import "core-js/proposals/string-replace-all"`.
Copy link
Member

@zloirock zloirock Mar 18, 2019

Choose a reason for hiding this comment

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

I am not sure that this is a clear enough wording. For polyfilling proposals, shippedProposals and proposals flags make sense only for usage. For entry, makes sense only the third option (and not only from proposals path - for example, import "core-js" includes import of all polyfills) without any flags.

- when using `useBuiltIns: "usage"` you have two different alternatives:
- set the [`shippedProposals`](#shippedproposals) option to `true`. This will enable polyfills and transforms for proposal which have already been shipped in browsers for a while.
- use `corejs: { version: 3, proposals: true }`. This will enable polyfilling of every proposal supported by `core-js`.

### `forceAllTransforms`

Expand Down Expand Up @@ -370,9 +415,10 @@ Toggles enabling support for builtin/feature proposals that have shipped in brow

The following are currently supported:

**Builtins**
**Builtins** injected when using `useBuiltIns: "usage"`

- [es7.array.flat-map](https://github.com/tc39/proposal-flatMap)
- [esnext.global-this](https://github.com/tc39/proposal-global) (only supported by `core-js@3`)
- [esnext.string.match-all](https://github.com/tc39/proposal-string-matchall) (only supported by `core-js@3`)
Copy link
Member

@zloirock zloirock Mar 18, 2019

Choose a reason for hiding this comment

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

Makes sense specify that will be injected only with useBuiltIns: usage.


**Features**

Expand Down