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

The esmodules target should be more future friendly #8809

Open
philipwalton opened this Issue Oct 3, 2018 · 6 comments

Comments

Projects
None yet
3 participants
@philipwalton

philipwalton commented Oct 3, 2018

Feature Request

I'm super glad to see the esmodules alias directly supported in preset-env, but I have concerns that it will very soon become mostly useless.

While it's true that today most module-supporting browsers are generally modern, that won't be true a few years from now. For example, when Chrome 86 ships in two years, Chrome 61 will seem horribly old, but people using the esmodules target will still be getting transpilations and polyfills applied for it.

Today the esmodules target is kind of like a whitelist for any browsers greater than or equal to the minimum module-supporting browsers versions specified here. But it'd actually be much better as a blacklist that filters out any browsers that don't support modules.

To understand the difference, consider what I currently do on my blog:

{
  targets: {
    browsers: [
      // The last two versions of each browser, excluding versions
      // that don't support <script type="module">.
      'last 2 Chrome versions', 'not Chrome < 60',
      'last 2 Safari versions', 'not Safari < 10.1',
      'last 2 iOS versions', 'not iOS < 10.3',
      'last 2 Firefox versions', 'not Firefox < 60',
      'last 2 Edge versions', 'not Edge < 16',
    ],
  },
}

I'd like to see the esmodule target work similarly. For example, I'd like to be able to do something like this:

{
  targets: {
    browsers: ['last 2 version, > 1%'],
    esmodules: true,
  },
}

And that would effectively turn my query into this:

{
  targets: {
    browsers: [
      'last 2 version, > 1%',
      'not Chrome < 60',
      'not Safari < 10.1',
      'not iOS < 10.3',
      'not Firefox < 60',
      'not Edge < 16',
      'not Opera < 48',
    ],
  },
}

This would allow me to specify my feature support exactly as I'm used to, but I'd be sure I wasn't getting any features not needed by browsers that work with <script type="module">.

/cc @kristoferbaxter

@babel-bot

This comment has been minimized.

Show comment
Hide comment
@babel-bot

babel-bot Oct 3, 2018

Collaborator

Hey @philipwalton! 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.

Collaborator

babel-bot commented Oct 3, 2018

Hey @philipwalton! 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.

@kristoferbaxter

This comment has been minimized.

Show comment
Hide comment
@kristoferbaxter

kristoferbaxter Oct 4, 2018

Contributor

I'm not certain I see the difference between these two cases since the lower bar determines the transpilation required afaik.

edge >= 16, firefox >= 60, safari >= 10.1, opera >= 48, ios_safari >= 10.3

should be treated equivalently to

  'last 2 version, > 1%',
  'not Chrome < 60',
  'not Safari < 10.1',
  'not iOS < 10.3',
  'not Firefox < 60',
  'not Edge < 16',
  'not Opera < 48',

Am I missing something?

Contributor

kristoferbaxter commented Oct 4, 2018

I'm not certain I see the difference between these two cases since the lower bar determines the transpilation required afaik.

edge >= 16, firefox >= 60, safari >= 10.1, opera >= 48, ios_safari >= 10.3

should be treated equivalently to

  'last 2 version, > 1%',
  'not Chrome < 60',
  'not Safari < 10.1',
  'not iOS < 10.3',
  'not Firefox < 60',
  'not Edge < 16',
  'not Opera < 48',

Am I missing something?

@philipwalton

This comment has been minimized.

Show comment
Hide comment
@philipwalton

philipwalton Oct 4, 2018

There's a subtle difference between the two. In the former you're including Chrome 60-67 (since current Chrome is 69), and in the latter you're only including Chrome 68-69 (speaking specifically about Chrome). And my point above was, in two years when the current Chrome version is 86 the former will include Chrome versions 60-84, and the latter will only include Chrome 85-86.

As more and more JS features get added to the language and get implemented in modern browsers, the need to care about Chrome 60 will go away, but the need to support IE11 will likely still be real.

That's why I say the esmodules target should exclude browsers that don't support modules rather than include all browsers that do.

philipwalton commented Oct 4, 2018

There's a subtle difference between the two. In the former you're including Chrome 60-67 (since current Chrome is 69), and in the latter you're only including Chrome 68-69 (speaking specifically about Chrome). And my point above was, in two years when the current Chrome version is 86 the former will include Chrome versions 60-84, and the latter will only include Chrome 85-86.

As more and more JS features get added to the language and get implemented in modern browsers, the need to care about Chrome 60 will go away, but the need to support IE11 will likely still be real.

That's why I say the esmodules target should exclude browsers that don't support modules rather than include all browsers that do.

@kristoferbaxter

This comment has been minimized.

Show comment
Hide comment
@kristoferbaxter

kristoferbaxter Oct 4, 2018

Contributor

It's an interesting idea, but it does break one specific part of the pattern.

Let's use the Chrome 86 example:
When configuration is layered as explained here, devices that support modules are not all guaranteed to work with the file referenced as type module.

Let's pretend Chrome 85 adds a feature, and our configuration here means the feature is not transpiled by Babel (browsers: ['last 2 version, > 1%'], esmodules: true). Now visitors who are on Chrome 83 receive a bundle that cannot be leveraged. This breaks the configuration model as it stands today.

Progressive transpilation is likely a better long term answer. With clear input signals from the user-agent regarding supported JS features transpilation can be far more exact.

However, I'd love to hear others thoughts as well, perhaps compatibility isn't as strong of a reason to continue with the model as I believe it is.

Contributor

kristoferbaxter commented Oct 4, 2018

It's an interesting idea, but it does break one specific part of the pattern.

Let's use the Chrome 86 example:
When configuration is layered as explained here, devices that support modules are not all guaranteed to work with the file referenced as type module.

Let's pretend Chrome 85 adds a feature, and our configuration here means the feature is not transpiled by Babel (browsers: ['last 2 version, > 1%'], esmodules: true). Now visitors who are on Chrome 83 receive a bundle that cannot be leveraged. This breaks the configuration model as it stands today.

Progressive transpilation is likely a better long term answer. With clear input signals from the user-agent regarding supported JS features transpilation can be far more exact.

However, I'd love to hear others thoughts as well, perhaps compatibility isn't as strong of a reason to continue with the model as I believe it is.

@philipwalton

This comment has been minimized.

Show comment
Hide comment
@philipwalton

philipwalton Oct 4, 2018

I mean, from my perspective the whole point of browserlist (and tools that use it like autoprefixer and babel-preset-env), is that you can specify a relative query and the required transforms/polyfills/vendor prefixes/etc. needed will slowly change over time.

Let's pretend Chrome 85 adds a feature, and our configuration here means the feature is not transpiled by Babel (browsers: ['last 2 version, > 1%'], esmodules: true). Now visitors who are on Chrome 83 receive a bundle that cannot be leveraged. This breaks the configuration model as it stands today.

It may break the new esmodules model, but I don't think it breaks the preset-env model, which (I believe) uses the browserlist default of > 0.5%, last 2 versions, Firefox ESR, not dead when no targets are specified.

That default is pretty inclusive, so if you exclude from that list any browsers that don't support modules, I think it'd be a fairly safe way to deploy ES module scripts.

philipwalton commented Oct 4, 2018

I mean, from my perspective the whole point of browserlist (and tools that use it like autoprefixer and babel-preset-env), is that you can specify a relative query and the required transforms/polyfills/vendor prefixes/etc. needed will slowly change over time.

Let's pretend Chrome 85 adds a feature, and our configuration here means the feature is not transpiled by Babel (browsers: ['last 2 version, > 1%'], esmodules: true). Now visitors who are on Chrome 83 receive a bundle that cannot be leveraged. This breaks the configuration model as it stands today.

It may break the new esmodules model, but I don't think it breaks the preset-env model, which (I believe) uses the browserlist default of > 0.5%, last 2 versions, Firefox ESR, not dead when no targets are specified.

That default is pretty inclusive, so if you exclude from that list any browsers that don't support modules, I think it'd be a fairly safe way to deploy ES module scripts.

@kristoferbaxter

This comment has been minimized.

Show comment
Hide comment
@kristoferbaxter

kristoferbaxter Oct 4, 2018

Contributor

The default configuration has a likely lowest common denominator of IE11 (https://browserl.ist/?q=%3E+0.5%25%2C+last+2+versions%2C+Firefox+ESR%2C+not+dead).

This is a pretty inclusive list, and is well served by the default nomodule script. However, if we narrow the definition of the module target its now possible to exclude support for newer user-agents supporting modules, but not a specific feature added post module support.

With the aforementioned recommendation, incompatibility is completely under the developer's control (I think that's really nice). But it's more likely to create scenarios where browsers are unsupported entirely. A tradeoff that is worth a bit of consideration.

Edit: This kind of incompatibility is why progressive transpilation is an interesting longer term solution for those willing to add a bit more complexity. And, hopefully, with clearer signals from browsers regarding supported features.

Double edit: Terms and language clarifications.

Contributor

kristoferbaxter commented Oct 4, 2018

The default configuration has a likely lowest common denominator of IE11 (https://browserl.ist/?q=%3E+0.5%25%2C+last+2+versions%2C+Firefox+ESR%2C+not+dead).

This is a pretty inclusive list, and is well served by the default nomodule script. However, if we narrow the definition of the module target its now possible to exclude support for newer user-agents supporting modules, but not a specific feature added post module support.

With the aforementioned recommendation, incompatibility is completely under the developer's control (I think that's really nice). But it's more likely to create scenarios where browsers are unsupported entirely. A tradeoff that is worth a bit of consideration.

Edit: This kind of incompatibility is why progressive transpilation is an interesting longer term solution for those willing to add a bit more complexity. And, hopefully, with clearer signals from browsers regarding supported features.

Double edit: Terms and language clarifications.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment