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’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(plugin-react): allow options.babel to be a function #6238

Merged
merged 4 commits into from
May 20, 2022

Conversation

cyco130
Copy link
Contributor

@cyco130 cyco130 commented Dec 22, 2021

Description

This PR adds an ssrPlugins options to plugin-react that overrides the babel.plugins option for SSR because sometimes different transforms are needed in the browser than on the server.

UPDATE: We settled on allowing options.babel to be a function to solve the same problem more generally instead.


What is the purpose of this pull request?

  • Bug fix
  • New Feature
  • Documentation update
  • Other

Before submitting the PR, please make sure you do the following

  • Read the Contributing Guidelines.
  • Read the Pull Request Guidelines and follow the Commit Convention.
  • Check that there isn't already a PR that solves the problem the same way to avoid creating a duplicate.
  • Provide a description in this PR that addresses what the PR is solving, or reference the issue that it solves (e.g. fixes #123).
  • Ideally, include relevant tests that fail without this PR but pass with it.

@cyco130 cyco130 changed the title plugin-react: optionally specify a different set of Babel plugins in SSR feat(plugin-react): optionally specify a different set of Babel plugins in SSR Dec 22, 2021
aleclarson
aleclarson previously approved these changes Dec 27, 2021
@aleclarson
Copy link
Member

Any reason for making it ssrPlugins and not babel.ssrPlugins? And what about ssrPresets?

@aleclarson
Copy link
Member

Alternatively, we could do an ssrOverrides option whose value is a Babel config object.

@aleclarson aleclarson self-requested a review December 27, 2021 15:59
@aleclarson aleclarson dismissed their stale review December 27, 2021 15:59

Unresolved questions

@cyco130
Copy link
Contributor Author

cyco130 commented Dec 28, 2021

Any reason for making it ssrPlugins and not babel.ssrPlugins? And what about ssrPresets?

Because babel was passed to Babel directly, this seemed less intrusive. But:

Alternatively, we could do an ssrOverrides option whose value is a Babel config object.

This is probably the way to go. I'll update my branch at the first opportunity.

@patak-dev
Copy link
Member

@cyco130 couldn't this be done with conditional config? It doesn't seem scalable to add ssrXXX for each option.

@cyco130
Copy link
Contributor Author

cyco130 commented May 19, 2022

@patak-dev it would work for build but not in dev. The idea is to be able to use different transforms when transform(code, id, options) is called with options.ssr == true even in dev.

BTW I noticed the new plugin.api.reactBabel API requires some more thinking. I had the idea to allow opt.babel to be a function to be called with id and options to open up even more possibilities at the expense of recreating the config for every file. Would that make sense?

@aleclarson
Copy link
Member

I had the idea to allow opt.babel to be a function to be called with id and options

I like this direction!

@cyco130 cyco130 force-pushed the feat-react-babel-separate-ssr-plugins branch from c1376b3 to 9c412a1 Compare May 19, 2022 15:57
@cyco130
Copy link
Contributor Author

cyco130 commented May 19, 2022

@aleclarson Updated to implement that idea.

@cyco130
Copy link
Contributor Author

cyco130 commented May 19, 2022

Hmm, maybe it would be best to pass id and options to plugin.api.reactBabel too? The if (typeof opts.babel !== "function") optimization won't work then.

aleclarson
aleclarson previously approved these changes May 19, 2022
packages/plugin-react/src/index.ts Show resolved Hide resolved
packages/plugin-react/src/index.ts Outdated Show resolved Hide resolved
packages/plugin-react/src/index.ts Show resolved Hide resolved
packages/plugin-react/src/index.ts Show resolved Hide resolved
@aleclarson
Copy link
Member

@patak-dev LGTM 🎸

@aleclarson aleclarson changed the title feat(plugin-react): optionally specify a different set of Babel plugins in SSR feat(plugin-react): let babel option be a function + add file/ssr props to api.reactBabel hooks May 19, 2022
@aleclarson aleclarson changed the title feat(plugin-react): let babel option be a function + add file/ssr props to api.reactBabel hooks feat(plugin-react): let babel option be a function + expose file/ssr values to api.reactBabel hooks May 19, 2022
@patak-dev patak-dev added p3-downstream-blocker Blocking the downstream ecosystem to work properly (priority) and removed needs rebase labels May 19, 2022
@patak-dev
Copy link
Member

This makes a lot more sense to me now. Isn't it too much to redo the babel plugins on each transform call? It seems inefficient. For the original use case, wouldn't a set of plugins that are computed once be enough? (like it was before being a function?).
I think we should properly justify having it on transform instead of being a one-off. Almost everything in Vite is configured once, and then filters (include/exclude).

@aleclarson
Copy link
Member

aleclarson commented May 19, 2022

Even before, Babel would resolve the plugins on every transformation, so the performance impact here is negligible.

For the original use case, wouldn't a set of plugins that are computed once be enough? (like it was before being a function?)

The Babel options object is cached in the staticBabelOptions variable if no api.reactBabel hooks exist and the babel plugin option is not a function, so the original use case works almost exactly like before, with the exception that now we can't safely reuse the Babel options if api.reactBabel hooks exist, because they might be using the new ssr and/or file properties exposed to them.

I think we should properly justify having it on transform instead of being a one-off. Almost everything in Vite is configured once, and then filters (include/exclude).

I'd say it's ideal to allow per-file configuration whenever possible, since it provides more flexibility. For example, higher level frameworks built on Vite might need to apply certain plugins based on file structure or in SSR only. It would hurt performance to implement their own Babel transformer.

@patak-dev
Copy link
Member

We got another +1 to merge this in today's team meeting. @cyco130 we can move forward once the tests are green 👍🏼

@cyco130
Copy link
Contributor Author

cyco130 commented May 20, 2022

I've fixed the related test but I don't quite understand the (probably unrelated) failing IIFE tests on MacOS. I'd appreciate some help with it :)

@patak-dev
Copy link
Member

I've fixed the related test but I don't quite understand the (probably unrelated) failing IIFE tests on MacOS. I'd appreciate some help with it :)

That was a glitch in Vite's CI, sorry about that

@cyco130 cyco130 force-pushed the feat-react-babel-separate-ssr-plugins branch from 1d120d2 to c3e8c5d Compare May 20, 2022 20:21
aleclarson
aleclarson previously approved these changes May 20, 2022
) {
const babelOptions = {
ssr,
file,
Copy link
Member

@aleclarson aleclarson May 20, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Another option is to use Object.defineProperties to define ssr and file options with enumerable: false (note this is the default when using defineProperties). That will prevent Babel from getting them, since non-enumerable properties are ignored by the spread operator.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I feel the intention would be less obvious and require a comment. But I can do that if you feel it'd be better.

Copy link
Member

@patak-dev patak-dev May 20, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why are these in the same object? I think the API would be more clear with three args. ssr and file are quite different than the rest of the object

type ReactBabelHook = (
  babelConfig: ReactBabelOptions,
  options: { ssr, file }, // or context?
  config: ResolvedConfig
) => void

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok let's do that, and I vote context as the name

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the changes @cyco130!

Sorry, one last question 👀
Why is it called file? Now that it is in the second parameter, should we rename it to id? file isn't that good in case there are virtual modules, no?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed (wasn't my idea anyway :P )

@cyco130 cyco130 force-pushed the feat-react-babel-separate-ssr-plugins branch from 7d3fcad to 284fc18 Compare May 20, 2022 21:43
@patak-dev patak-dev changed the title feat(plugin-react): let babel option be a function + expose file/ssr values to api.reactBabel hooks feat(plugin-react): allow options.babel to be a function May 20, 2022
@patak-dev patak-dev merged commit f4d6262 into vitejs:main May 20, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
p3-downstream-blocker Blocking the downstream ecosystem to work properly (priority)
Projects
Archived in project
Development

Successfully merging this pull request may close these issues.

5 participants