Skip to content

Feature request: better polyfill experience for modern targets #21014

@nulladdict

Description

@nulladdict

Description

Currently there are two main ways of adding polyfills to modern builds. Using an external polyfill service or using plugin-legacy with modern options. In this issues I want to focus on the plugin-legacy experience

If users want to only add polyfills to modern build they need to do one of:

  • Declare them upfront using modernPolyfills: string[] which feels somewhat pointless because they can just import the modules directly in the main entrypoint instead and skip the plugin altogether
  • Use auto-detection with modernPolyfills: true, modernTargets: string | string[] which will auto-detect used features and inject polyfills

Auto detection relies on babel (through babel-plugin-polyfill-corejs3 and babel-plugin-polyfill-regenerator) which leads to a couple of consequences

First, plugin needs to transform all chunks using babel. babel is slower than swc but since it transforms built chunks (as far as I understand) it shouldn't be a big issue

Second, the syntax for targets in esbuild and babel is very different. esbuild (and vite) currently do not support browserslist while babel does. This leads to a bit of a confusion

esbuild and browserslist are not entirely compatible. There's browserslist-to-esbuild library that can convert from browserslists targets to esbuild. The conversion is lossy and discards anything that isn't supported by esbuild (e.g. samsung internet)

Before #20393 users had to set both build.target and modernTargets and were fully in control of what gets built with what target

After the PR users now have to unset build.target and set modernTargets which will transform browserslist query and set the esbuild target. This feels somewhat backwards (why does a plugin control the target and not the other way around?) and in rare cases can change the output (if the targets were sufficiently different)

Suggested solution

The ideal solution is for oxc, rolldown and then vite to support functionality that plugin-env provides. This way users can use oxc-based polyfill detection and entirely avoid plugin-legacy for modern build

As far as I could see, there's scaffolding for this in oxc but the functionality is not implemented yet and I have to idea if it's on the roadmap

Other solution is to teach plugin-legacy to use build.target as modernTargets which is more intuitive but requires syntax conversion. I'm not entirely sure it's possible since esbuild supports targets such as es2020 and browserslist doesn't. I'll investigate and post results in comments

Alternative

Do nothing and accept the current state. Maybe add a bit more clarity to plugin-legacy docs

Docs for modernTargets currently say:

  • the option will override build.target
  • if the option is not set it will fallback to the default value
  • the option should not be set if the plugin renders legacy chunks

To me a couple of questions arise:

  • if I don't set the option would build.target still be replaced by some default?
    • won't build.target fallback to its default value?
  • if I want to both render legacy chunks and add modern polyfills what do I do?

Additional context

No response

Validations

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions