website icon indicating copy to clipboard operation
website copied to clipboard

Default targets for preset-env shall be “defaults”

Open dilyanpalauzov opened this issue 5 years ago • 12 comments

No .browserslist file implies a .browserslist file with content default, and this means support for IE 11 and this means, as of https://kangax.github.io/compat-table/es6/, only some ES2015/ES6.

https://babeljs.io/docs/en/babel-preset-env#targets says “Sidenote, if no targets are specified, @babel/preset-env will transform all ECMAScript 2015+ code by default.”

Apart from the fact that there is a “caveat” dead-link-hint above this citation, assuming the wording means ”will transform TO ES2015+ by default" (thus it will run on any ES2015 javascript engine), please change the default of no "targets", do mean targets: "defaults".

dilyanpalauzov avatar May 12 '20 14:05 dilyanpalauzov

Hey @dilyanpalauzov! We really appreciate you taking the time to report an issue. The collaborators on this project attempt to help as many people as possible, but we're a limited number of volunteers, so it's possible this won't be addressed swiftly.

If you need any help, or just have general Babel or JavaScript questions, we have a vibrant Slack community that typically always has someone willing to help. You can sign-up here for an invite."

babel-bot avatar May 12 '20 14:05 babel-bot

@dilyanpalauzov the initial intent of preset-env was to replace preset-latest, that is, transform all ES2015+ code down to ES5.

Changing the behavior of "no targets" is a breaking change. Check out a few relevant discussions: https://github.com/babel/babel/pull/8897#issuecomment-490659840, https://github.com/babel/babel/issues/9962, and ultimately the PR that will land in Babel 8: https://github.com/babel/babel/pull/10897

existentialism avatar May 12 '20 15:05 existentialism

The default for preset-latest means es2015, es2016, and es2017. But the default for preset-env is “Sidenote, if no targets are specified, @babel/preset-env will transform all ECMAScript 2015+ code by default.”

This needs rewording like, “the resulting code will require ES2017 conformant engine”. I really do not understand what is written there.

dilyanpalauzov avatar May 12 '20 15:05 dilyanpalauzov

Yeah... if no target is specified all ES2015+ code will be transformed (same as preset-latest behavior)?

existentialism avatar May 12 '20 15:05 existentialism

There is source language and target language.

“will transform all ECMAScript 2015+ code by default.” means that the source language is ES2020, e.g. the input can containing optional chaining. I mean, I read it as “transform FROM". It does not say anything about ”transform TO (version)”.

In its current writing “transform” is transitive verb, https://www.merriam-webster.com/dictionary/transform . But for the “to become transformed” the intransitive verb is needed.

E.g. "preset-env transforms A” means “preset-evn changes A”. It does not say to what is A changed.

dilyanpalauzov avatar May 12 '20 15:05 dilyanpalauzov

Happy to change the language to reduce confusion, would you like to send a PR?

existentialism avatar May 12 '20 15:05 existentialism

My reading is that targets: accepts only browserslist queries and the browserslist does not accept "es2020" as input. So targets can be only a list of browsers with corresponding versions. ES2015+ is not a browserslist query and I cannot write what the default for targets is.

So something like this:

Sidenote, if no targets are specified, the default is targets:{a browserslist query}.

or

Sidenote, if no targets are specified, the default is not to transpile.

or

Sidenote, if no targets are specified, the default is only to transpile code that has not reached stage 4 in TC39.

dilyanpalauzov avatar May 12 '20 15:05 dilyanpalauzov

Hey @dilyanpalauzov! We really appreciate you taking the time to report an issue. The collaborators on this project attempt to help as many people as possible, but we're a limited number of volunteers, so it's possible this won't be addressed swiftly.

If you need any help, or just have general Babel or JavaScript questions, we have a vibrant Slack community that typically always has someone willing to help. You can sign-up here for an invite.

babel-bot avatar May 12 '20 16:05 babel-bot

I iterate once again over the documentation of preset-env in this regard.

The top of https://babeljs.io/docs/en/babel-preset-env#browserslist-integration says:

By default @babel/preset-env will use browserslist config sources unless either the targets or ignoreBrowserslistConfig options are set.

⇒ This means, that .browserlist is read, when targets: is “not set”. Does targets:{} set targets? I do not get the point of the latter construct, neither its purpose.

Later the description says, https://babeljs.io/docs/en/babel-preset-env#targets:

Sidenote, if no targets are specified, @babel/preset-env will transform all ECMAScript 2015+ code by default.

⇒ This means, that if no targets are specified, but targets: is set (?), considering the correspondence so far here, the code will run in ES2020 environments and no transpilation will be done. Or it means, that targets:{} achieves this ES2020 effect, but no-targets reads .browserslist?

In any case, from the perspective of the users, missing .browserslist is the same as .browserslist that contains defaults and when preset-env falls-back to .browserslist, it shall fall back to defaults, when .browserslist is absent.

It is just unclear when preset-env falls back to .browserslist.

dilyanpalauzov avatar May 13 '20 18:05 dilyanpalauzov

It is just unclear when preset-env falls back to .browserslist.

We will fall back to a browserslist config if you do not have the targets key set and do not have ignoreBrowserslistConfig set in your Babel config.

Hence:

By default @babel/preset-env will use browserslist config sources unless either the targets or ignoreBrowserslistConfig options are set.

Happy to work on making this more clear.

=====

What does ignoreBrowserslistConfig do?

This means, that .browserlist is read, when targets: is “not set”. Does targets:{} set targets? I do not get the point of the latter construct, neither its purpose.

When you have no targets specified in ones Babel config but have the ignoreBrowserslistConfig option set:

{
  "presets": [["@babel/preset-env", { "ignoreBrowserslistConfig": true }]]
}

And have a browserslist config (whether its a .browserslistrc or key in package.json), it will be ignored.

This option exists because we had users who had a browserlist config but did not want their preset-env to use it.

=====

I iterate once again over the documentation of preset-env in this regard.

And I'll try and explain once again:

If there are no targets specified in ones Babel config:

{
  "presets": ["@babel/preset-env"]
}

And there are no browserslist config (whether its a .browserslistrc or key in package.json), then all transforms are applied.

This is what we mean by "if no targets are specified, @babel/preset-env will transform all ECMAScript 2015+ code by default".

This is also the important difference from browserlist's behavior of falling back to the defaults query when no config is set.

Changing this behavior is a breaking change, hence why any change won't land until Babel 8.

=====

I want to make it clear that we are absolutely open and actively want to improve the docs and thank you for raising issues.

existentialism avatar May 17 '20 21:05 existentialism

Do I understand correctly, that

{
  "presets": ["@babel/preset-env"]
}

means:

  1. If there is .browserslist file, then iterpret that file and do whatever it says
  2. If there is no .browserslist file, then target is es2015?

For the record: @babel/preset-env will use browserslist config sources means, that on missing .broswerslist then according to browserslist, this it IE11 (because the absense of a .browserslist file applies valid config for browserslist).

Can you write instead from:

By default @babel/preset-env will use browserslist config sources unless either the targets or ignoreBrowserslistConfig options are set.

to

@babel/preset-env will use browserslist config sources, when the option object for the preset does not have the properties targets or ignoreBrowserslistConfig .

So that

{
  "presets": [["@babel/preset-env", {ignoreBroswerslistConfig: false}]]
}

and

{
  "presets": [["@babel/preset-env", {ignoreBroswerslistConfig: true}]]
}

and

{
  "presets": [["@babel/preset-env", {ignoreBroswerslistConfig: undefined}]]
}

and

{
  "presets": [["@babel/preset-env", {targets: undefined}]]
}

mean the same (etiher ignoreBroswerslistConfig or targets is set/present), so .browserslist is skipped. This is what the current text says. In fact, ignoreBrowserslistConfig can be deprecated, as the presence of the target property of the options object, toggles in the same way the behaviour, and having both targets and ignoreBrowserlistConfig has no added value, compared to having just ‘targets` present

And later, from:

Since one of the original goals of preset-env was to help users easily transition from using preset-latest, it behaves similarly when no targets are specified: preset-env will transform all ES2015-ES2020 code to be ES5 compatible.

to

Since one of the original goals of preset-env was to help users easily transition from using preset-latest, it behaves similarly when {targets:undefined}, {targets:null} or {targets:""} and alike are used, or when targets and .browserslist are absent: preset-env will transform all ES2015-ES2020 code to be ES5 compatible.

Nota Bene: having no .browserslist file when the targets property is absent, then the target is set to ES5. Having .browserlslist file with content defaults, when the targets property is not set, then the expansion of defaults is applied. This is different from browserslist behaviour, which implies defaults when no .browserslist file is present.

Thank you!

dilyanpalauzov avatar May 17 '20 22:05 dilyanpalauzov

What happens with

{
  "presets": ["@babel/preset-env"]
}

and there is .browserslist file that is empty? Is then the target IE 11/defaults?

dilyanpalauzov avatar May 17 '20 23:05 dilyanpalauzov