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鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

What do we need to make usage-global injection work with @babel/runtime? #16391

Open
1 task
nicolo-ribaudo opened this issue Mar 28, 2024 · 2 comments
Open
1 task

Comments

@nicolo-ribaudo
Copy link
Member

nicolo-ribaudo commented Mar 28, 2024

馃捇

  • Would you like to work on this feature?

What problem are you trying to solve?

@nyngwang has been going around a bit checking how our polyfill injection works (thank you very much!), and after going through their comments I realized that our injection story for usage-global is pretty bad when it comes to helpers.

If you have this config:

{
  "plugins": [
    "@babel/transform-runtime"
  ]
}

Babel will inject imports for helpers like import _typeof from "@babel/runtime/helpers/typeof".

Then you decide that you want to inject global polyfills through core-js, so you update your config to this:

{
  "plugins": [
    "@babel/transform-runtime",
    ["babel-plugin-polyfill-corejs3", { "method": "usage-global" }]
  ]
}

now Babel will inject imports like import "core-js/modules/es.array.flat.js";, but suddently your imports for helpers will become import "@babel/runtime-corejs3/helpers/typeof" (which depends on core-js-pure). This is to make sure that the helpers are also polyfilled, but:

  • you asked for global-modifying polyfills, and now in your dependencies you have both core-js and core-js-pure
  • injecting global polyfills forced you to change one of your dependencies.

If you still want to use @babel/runtime (because @babel/runtime-corejs3 includes polyfills down to ES5), you have to instead use this config:

{
  "plugins": [
    ["@babel/transform-runtime", { "moduleName": "@babel/runtime" }],
    ["babel-plugin-polyfill-corejs3", { "method": "usage-global" }]
  ]
}

NOTE: I think this behavior is good when it comes to usage-pure, because we are just changing the @babel/runtime imports to a different package that uses exactly the pure polyfill the user asked for.

Describe the solution you'd like

What if for each helper we maintained the list of built-ins that it relies on, and when injecting a import "@babel/runtime/typeof/helpers" we called the polyfill provider saying "hey, we included a helper that uses Symbol and Array.prototype.flat: if needed for the configured target, consider injecting imports to these polyfills".

Then, when compiling typeof foo and using ["babel-plugin-polyfill-corejs3", { "method": "usage-global" }], we would generate some code like

import "core-js/modules/es.symbol.js";
import _typeof from "@babel/runtime/helpers/typeof";

_typeof(foo);

rather than

import _typeof from "@babel/runtime-corejs3/helpers/typeof";

_typeof(foo);

This list would probably need to be manually-maintained by us for each helper, and:

  • we could try linting using our existing polyfill provider infrastructure, to make sure that we aren't missing any builtin in our list
  • even if we change the helper to not rely on X anymore, we still need to include X in the list of features for compatibility with older @babel/runtime versions

Describe alternatives you've considered

Do nothing

Documentation, Adoption, Migration Strategy

No response

@zloirock
Copy link
Member

zloirock commented Mar 28, 2024

I don't remember how internally works @babel/transform-runtime, but what about a naive solution like this?

  1. Inject a helper as usually, without runtime
  2. Inject core-js polyfills via babel-plugin-polyfill-corejs3 for code and this helper as usually
  3. Just replace this helper to import from runtime

It looks slower than the predefined list of dependencies but simpler for maintenance.

@nyngwang
Copy link

As I'm a naive user, I like what @zloirock proposed as it has the following two advantages:

  1. No more confusion about why "my code" does not include those extracted helpers when adding polyfills for my code. (If the link does not highlight the specific sentence, please search the page with: but with that config babel includes polyfills when you use that feature in your code!)
    • In short, they tried to teach people that the option useBuiltIns: 'usage' might miss some polyfills because "code of helpers" is not included in "my code" when determining what needs to be polyfilled. It was very frustrating when I tried to understand the entire thread. The thread is still open btw.
  2. It can be easily explained/documented in one simple sentence without leaky abstractions:
    • babel-plugin-polyfill-corejs3 will add all polyfills you need to run your app/library for your browser targets.
    • @babel/transform-runtime will extract helpers. Extracting it or not has nothing to do with whether my app/library will be polyfilled correctly.

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

No branches or pull requests

3 participants