{"action":"created","issue":{"url":"https://api.github.com/repos/babel/babel/issues/8195","repository_url":"https://api.github.com/repos/babel/babel","labels_url":"https://api.github.com/repos/babel/babel/issues/8195/labels{/name}","comments_url":"https://api.github.com/repos/babel/babel/issues/8195/comments","events_url":"https://api.github.com/repos/babel/babel/issues/8195/events","html_url":"https://github.com/babel/babel/issues/8195","id":333379659,"node_id":"MDU6SXNzdWUzMzMzNzk2NTk=","number":8195,"title":"RFC: Better babel-preset-env API","user":{"login":"rtsao","id":780408,"node_id":"MDQ6VXNlcjc4MDQwOA==","avatar_url":"https://avatars0.githubusercontent.com/u/780408?v=4","gravatar_id":"","url":"https://api.github.com/users/rtsao","html_url":"https://github.com/rtsao","followers_url":"https://api.github.com/users/rtsao/followers","following_url":"https://api.github.com/users/rtsao/following{/other_user}","gists_url":"https://api.github.com/users/rtsao/gists{/gist_id}","starred_url":"https://api.github.com/users/rtsao/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/rtsao/subscriptions","organizations_url":"https://api.github.com/users/rtsao/orgs","repos_url":"https://api.github.com/users/rtsao/repos","events_url":"https://api.github.com/users/rtsao/events{/privacy}","received_events_url":"https://api.github.com/users/rtsao/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":7,"created_at":"2018-06-18T18:13:45Z","updated_at":"2018-07-09T19:58:40Z","closed_at":null,"author_association":"CONTRIBUTOR","body":"## Feature Request\r\n\r\n**Is your feature request related to a problem? Please describe.**\r\n\r\n\r\nFirst off, major props for creating such an incredibly awesome feature 😄. I think it's fair to say the `env` preset is truly game-changing and should be regarded as a huge milestone in advancing the JS ecosystem forward.\r\n\r\nHowever, I think at times the existing configuration and mechanics of the `env` preset can be unintuitive, suboptimal, and/or lacking for certain common use cases.\r\n\r\nVarious aspects of this have already been discussed in several related issues:\r\n\r\n- https://github.com/babel/babel/issues/6830\r\n- https://github.com/babel/babel/issues/8155\r\n- https://github.com/babel/babel/issues/5699\r\n- https://github.com/babel/babel/issues/6628\r\n- https://github.com/babel/babel/issues/7267\r\n- https://github.com/babel/babel/issues/6626\r\n- https://github.com/babel/babel/issues/6613\r\n  - https://github.com/babel/babel/pull/6731\r\n\r\n**Describe the solution you'd like**\r\n\r\nTo address many of these issues, I propose the following configuration interface for the `env` preset:\r\n\r\n**`options.targets`**\r\n\r\n- `targets[\"chrome\" | \"firefox\" | \"edge\" | ...]` *(unchanged)*\r\n- `targets.browsers` *(unchanged)*\r\n- `targets.node` *(unchanged)*\r\n- `targets.esmodules` *(unchanged)*\r\n- ❌ ~~`targets.uglify`~~ Note: already deprecated\r\n- 🆕 `targets.spec`\r\n\r\nThis option is used to target a specific minimum ES specification, with support for the following values:\r\n - `\"es5\"`\r\n - `\"es2015\"`\r\n - `\"es2016\"`\r\n - `\"es2017\"`\r\n - `\"es2018\"`\r\n\r\nThis option is useful when targeting various tools using a parser supporting a particular ECMAScript specification (e.g. Uglify, webpack, etc.).\r\n\r\nThis option is also especially useful for library authors, allowing them to explicitly specify a minimum supported version of ECMAScript for their library, or even publish multiple variants of their code.\r\n\r\n❌ ~~**`options.forceAllTransforms`**~~\r\n\r\nReplaced by `options.target.spec`. In my opinion, `{forceAllTransforms: true}` is really just a more amiguous way of saying `{targets: {spec: \"es5\"}}`, which also reduces the configuration surface area by elegantly fitting into the existing \"targets\" paradigm.\r\n\r\n**`options.modules`**\r\n\r\n*(unchanged)*\r\n\r\n🆕 **`options.transformMode`**\r\n\r\nThis option replaces the existing top-level `spec` and `loose` options for the preset and supports the following values:\r\n\r\n- `\"normal\"` - Use the default configuration of plugins, generally corresponding to a pragmatic balance between performance and spec compliance, (i.e. `spec: false`, `loose: false` for transforms that support these options)\r\n- `\"performance\"` - When possible, bias plugin configuration towards high performance, (i.e. `spec: false`, `loose: true` for transforms that support these options)\r\n- `\"compliance\"` - When possible, bias plugin configuration towards rigorous spec compliance, (i.e. `spec: true`, `loose: false` for transforms that support these options)\r\n\r\nCurrently, transforms only support `spec` or `loose` options, but it stands to reason that more granular/nuanced plugin configuration might exist in the future. In this case, these overarching modes can still applied in a sensible manner because it corresponds to high-level intent.\r\n\r\n❌ ~~**`options.loose`**~~\r\n\r\nReplaced by `options.transformMode` (see above).\r\n\r\n❌ ~~**`options.spec`**~~\r\n\r\nReplaced by `options.transformMode` (see above).\r\n\r\n**`options.include`**\r\n\r\n*(unchanged)*\r\n\r\n**`options.exclude`**\r\n\r\n*(unchanged)*\r\n\r\n🆕 **`options.configOverrides`**\r\n\r\nThis option allows for overriding the configuration of specific plugins when they are applied by the preset (i.e. the plugin matches the target).\r\n\r\nExample:\r\n```\r\n{\r\n  configOverrides: {\r\n   \"transform-arrow-functions\": {loose: true}\r\n  }\r\n}\r\n```\r\n\r\n**`options.shippedProposals`**\r\n\r\n*(unchanged)*\r\n\r\n🆕 **`options.polyfills`**\r\n- `true` - Adds corresponding import statements to core-js polyfills for used built-ins (as required by the target environment), akin to the existing `{useBuiltins: \"usage\"}` option.\r\n- `false` - Do not add polyfills, regardless of environment\r\n- `{[string]: string}` - Same as `true`, but using provided object mapping from core-js polyfills to custom polyfill packages.\r\n\r\n```\r\n{\r\n  polyfills: {\r\n    \"es6.promise\": \"some-custom-promise-polyfill-pkg\"\r\n  }\r\n}\r\n```\r\n\r\nAs an aside, I think the behavior from the existing `{useBuiltIns: \"entry\"}` behavior should be removed from this preset. Unlike `{useBuiltIns: \"usage\"}`, it doesn't take any advantage of the static analysis faciliated by Babel. Instead, it blindly imports all polyfills *possibly* needed in the target environment, regardless of *actual* usage.\r\n\r\nIn my opinion, this sort of behavior would be more appropriately handled by a bundler (e.g. a webpack plugin taking the same target configuration as the env preset that replaces the import). This might be facilitated by exposing part of the env preset implementation as a semi-generic package that takes a target configuration and returns a list of required transforms/polyfills (akin to the existing `{debug: true}` option).\r\n\r\nHowever, should there be any disagreement concerning this, I'd love to discuss potential alternatives.\r\n\r\n❌ ~~**`options.useBuiltIns`**~~\r\n\r\nReplaced by `options.polyfills` (see above).\r\n\r\n🆕 **`options.externalHelpers`**\r\n\r\n- `true` - Import and reference the standard external babel helpers package(s)\r\n- `false` - Use standard babel inline helpers\r\n- `{[string]: string}` - Same as `true`, but using provided object mapping from external helper packages to custom helper packages. For example:\r\n\r\n```\r\n{\r\n  externalHelpers: {\r\n    \"extends\": \"some-custom-extends-helper\"\r\n  }\r\n}\r\n```\r\n\r\n**`options.debug`**\r\n\r\n*(unchanged)*\r\n\r\n**`options.ignoreBrowserslistConfig`**\r\n\r\n*(unchanged)*\r\n\r\n**`options.configPath`**\r\n\r\n*(unchanged)*\r\n\r\n**Describe alternatives you've considered**\r\n\r\n - Rule-based configuration, akin to the system used in webpack.\r\n   - This is good method for allowing extensive customization, but I think this is more complexity than needed for the env preset.\r\n - Not adding support for per-plugin custom configuration.\r\n   - I think this is useful for power users who are choosy with regard to `loose`/`spec` options on an individual basis. In my opinion, the cost of adding support for this is pretty low, both in terms of implementation complexity and additional API surface area.\r\n - Not adding support for polyfill customization\r\n   - I think this is also needed for power users who may want to use polyfills other than `core-js`.\r\n - Preserving existing `{useBuiltIns: \"entry\"}` behavior\r\n   - Removing this behavior allows for simpler configuration. Instead, the logic for determining which polyfills are needed based on env should be exposed as a generic package, which could be used by bundler-level plugins to perform this.\r\n\r\n**Teachability, Documentation, Adoption, Migration Strategy**\r\n\r\nI think this configuration is considerably more intuitive and straightforward than the existing configuration. Documentation would essentially consist of the above section. In terms of migration strategy, the old options could be marked as deprecated and then removed in the next major version.\r\n\r\nP.S. I'd be more than willing to fully or partially implement this, I'd just like to achieve consensus and buy-in from maintainers in terms of the path forward.\r\n"},"comment":{"url":"https://api.github.com/repos/babel/babel/issues/comments/403601303","html_url":"https://github.com/babel/babel/issues/8195#issuecomment-403601303","issue_url":"https://api.github.com/repos/babel/babel/issues/8195","id":403601303,"node_id":"MDEyOklzc3VlQ29tbWVudDQwMzYwMTMwMw==","user":{"login":"rtsao","id":780408,"node_id":"MDQ6VXNlcjc4MDQwOA==","avatar_url":"https://avatars0.githubusercontent.com/u/780408?v=4","gravatar_id":"","url":"https://api.github.com/users/rtsao","html_url":"https://github.com/rtsao","followers_url":"https://api.github.com/users/rtsao/followers","following_url":"https://api.github.com/users/rtsao/following{/other_user}","gists_url":"https://api.github.com/users/rtsao/gists{/gist_id}","starred_url":"https://api.github.com/users/rtsao/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/rtsao/subscriptions","organizations_url":"https://api.github.com/users/rtsao/orgs","repos_url":"https://api.github.com/users/rtsao/repos","events_url":"https://api.github.com/users/rtsao/events{/privacy}","received_events_url":"https://api.github.com/users/rtsao/received_events","type":"User","site_admin":false},"created_at":"2018-07-09T19:58:40Z","updated_at":"2018-07-09T19:58:40Z","author_association":"CONTRIBUTOR","body":"A couple minor adjustments to the RFC:\r\n\r\n```diff\r\n- defaultTransformMode: \"performance\" | \"compliance\"\r\n+ transformMode: \"normal\" | \"performance\" | \"compliance\"\r\n```\r\n\r\nAfter some more deliberation, I think this is terser and less confusing. I also forgot there needs to be a `\"normal\"` option which corresponds to default behavior (i.e. `{loose: false, spec: false}`)"}}
{"actor":{"display_login":"rtsao"}}