Repository navigation
Let jsxImportSource be configurable through tsconfig.json #9847
Description
Is your proposal related to a problem?
Right now it's only suggested for tsconfig.json to set "jsx": "react" but it's not enforced.
TS 4.1 will bring new JSX-related option (jsxImportSource) and new possible values for the jsx option (react-jsx & react-jsxdev) - both of those changes are related to the new JSX runtimes.
TS also has an ability to change what exact JSX namespace is used for type-checking based on the used jsx factory as per the documentation. This probably means that there is a problem for some possible configuration today:
TS can do its typechecking thinking that another factory is used (when one would configure jsxFactory) but in fact the emitted code uses the default factory of React.createElement because the transpilation is done by Babel that is not aware of TS configuration.
I'm not really interested in fixing this problem - I haven't found any issue about this so the audience for this is probably very little and it's just a possible problem that I have thought of and not something that affects me.
However, I would really love to be able to configure jsxImportSource globally and while you don't allow for Babel customization (which is understandable tradeoff here) you allow for some tsconfig.json configuration. It (tsconfig.json) seems to be a good match for inferring this particular configuration for a vast number of consumers (as TS is used by a lot of people).
Motivation
I'm a maintainer of Emotion which is a popular CSS-in-JS solution for React (3.4M downloads/week) which comes with the CSS prop API that is based on @jsx pragma (although not all of our consumers use the CSS prop API as we expose the popular styled API as well).
Right now the @jsx pragma in CRA has to be used all over the place. We personally don't find it to be that problematic but we get complaints about this regularly from the community. Having a way to configure this (new transforms, not the old pragma) globally in CRA would probably result in a huge DX improvement for us.
Describe the solution you'd like
Provide custom importSource to @babel/preset-react, based on the jsxImportSource from tsconfig.json
Describe alternatives you've considered
If this is something that you don't want to support then I strongly believe that you should disallow configuring jsxImportSource in the tsconfig.json altogether because it causes a configuration mismatch between TS and Babel and this might be a footgun for people.
- Implementation intent
Activity
seanbruce commentedon Nov 1, 2020
I created a new project using CRA4 with typescript template today.
I have a difficult time trying to use emotion. as I know with the release version 10.1.0 of emotion, I should use /** @jsxImportSource @emotion/core /` instead of /* @jsx jsx */, so I try to use like this
or just
but I got error anyway saying "'React' refers to a UMD global, but the current file is a module. Consider adding an import instead.". I guess maybe it's about CRA typescript template.
I'm not familiar with neither CRA nor new JSX runtime.
Andarist commentedon Nov 1, 2020
Could u share a repository with this issue reproduced? I could take a look at this.
seanbruce commentedon Nov 1, 2020
@Andarist Thanks! here is the repository https://github.com/seanbruce/butler-of-ellen.git
Andarist commentedon Nov 1, 2020
The current TS version is not aware of the new
@jsxImportSourceand thus it doesn't know that there are already implicit imports (inserted automatically) based on that@jsxImportSourcepragma. This requires TS 4.1 which is currently at the beta stage and I believe that it is supposed to be shipped as stable this month.I've managed to trick the compiler to accept this by changing this:
https://github.com/seanbruce/butler-of-ellen/blob/28754637234e145547f16232fe5eef111457a651/tsconfig.json#L18
to
"preserve"And by adding
import '@emotion/core'to this file:https://github.com/seanbruce/butler-of-ellen/blob/28754637234e145547f16232fe5eef111457a651/src/react-app-env.d.ts
seanbruce commentedon Nov 2, 2020
following this trick. I change compilerOptions.jsx to "preserve" and add change react-app-env.d.ts like this
then I run yarn start I got this error says
TypeError: Cannot assign to read only property 'jsx' of object '#<Object>'Andarist commentedon Nov 2, 2020
Oh, right 😢 I've focused on fixing TS problems without running
yarn startand CRA enforces certain values to be what they want them to be. Those are enforced values:https://github.com/facebook/create-react-app/blob/aec42e2cc05fe0799a3b73830b874757e9e3f561/packages/react-scripts/scripts/utils/verifyTypeScriptSetup.js#L148-L158
I'll give this more thought but I don't have an idea how this can be approached right now without waiting for TS 4.1
seanbruce commentedon Nov 2, 2020
@Andarist I think I just wait for TS4.1 released to solve this issue once and for all. for now, I use this not perfect solution until TS4.1. Thank you so much for your time.😄
FinPlorer commentedon Dec 3, 2020
With version Typescript 4.1 I tried
But the css props from emotion is not working, I have to put "/** @jsxImportSource @emotion/react */" on top on the file.
Is the property jsxImportSource ignored ?
Andarist commentedon Dec 3, 2020
And this issue is exactly about this problem. I'm proposing that the CRA's Babel preset could be "configured" with the
importSourcebased on thejsxImportSourceof thetsconfig.json. I believe that wouldn't compromise the 0config approach taken by the CRA.stephenh commentedon Jan 14, 2021
@iansu fyi this feature (being able to pass
importSourceto babel) would be a big usability win for CRA's CSS-in-JS users (i.e. emotion/et al) by being able to remove the/** jsxImportSource ... */lines that currently have to be copy/pasted into every file in a project.It looks like this PR added an
importSourcewith aprocess.env.JSX_IMPORT_SOURCEflag:https://github.com/facebook/create-react-app/pull/10138/files#diff-7cd8a2246cedc973ca54463e12073aaff89e13fda0f3d8b61742ec8e2b64b708R100
But @Andarist is suggesting adding a smarter if-
isTypeScriptEnabled-then-parse-tsconfig-for-its-jsxImportSourcesetting, right around this section of code from your "New JSX Transform Opt Out" PR:https://github.com/facebook/create-react-app/blame/master/packages/babel-preset-react-app/create.js#L99
If I wrote a PR that changed that ~section of code to conditionally parse
tsconfig.jsonand pass alongimportSourceto babel, would that likely get accepted? Do you have any preferences/suggestions for a better approach?Thanks!
(...I'm a little worried about "just fs.load
tsconfig.json; while really simple, it wouldn't support tsconfigs that extend other tsconfigs ... would have to research the idiomatic way of loading tsconfigs...although maybe that could be a V2.)Andarist commentedon Jan 14, 2021
TS exposes the API to read the config file so that part shouldn't be particularly a problem: https://github.com/facebook/create-react-app/blob/aec42e2cc05fe0799a3b73830b874757e9e3f561/packages/react-scripts/scripts/utils/verifyTypeScriptSetup.js#L173-L176
onpaws commentedon Feb 1, 2021
@stephenh Curious if you had the chance to start the PR you mentioned?
I just created a new CRA4 app + Emotion 11 and ran into this - completely agree it will be awesome for CRA users if they don't have to manually prepend
/** @jsxImportSource @emotion/react */on a per-file basis.
onpaws commentedon Feb 1, 2021
@MatthieuCoelho Yes, it seems that way. On CRAv4.0.1 + Emotion v11.1.4 I was able to repro what you're describing - this property seems to not get picked up by
react-scriptswhich makes sense since it only arrived with TS v4.1+.Is anyone aware of existing PRs that start to make CRA aware of TypeScript 4.1?
7 remaining items
55Cancri commentedon May 17, 2022
I'm currently running a vite application and the emotion docs (https://emotion.sh/docs/typescript) suggest updating the tsconfig compiler options with:
but this does not work- I still need to add
/** @jsxImportSource @emotion/react */above each file. What am I missing?gimurpe commentedon Nov 17, 2022
Any news on this ?
fix: jsx pragma change needed with upgradet to react 17
guopingxiao commentedon Dec 1, 2022
need to add /** @jsxImportSource @emotion/react */ above each file is very hard for devlopers
ALFmachine commentedon Dec 28, 2022
👍
baba43 commentedon Feb 20, 2023
Oh man, this problem is really annoying for the developer experience. In our project, the css prop worked for a long time, until some update. Unfortunately, the bug is noticed only in the application and not in the development process.
I don't want to complain, because I am very thankful for all the time invested in open source tools here. However, this problem is so prominent in Google searches that it really should be addressed.
claudiamatosa commentedon Mar 1, 2023
In case this helps anyone: if your configuration is ejected and you have access to the Webpack config file, you can use the ModifySourcePlugin to prepend the
jsxImportSourcecomment to every file:I added it at the start of the plugins list, which seemed to do the trick. It's not ideal, but I couldn't bear the thought of adding this at the top of every file. 😅
Gittified commentedon Apr 15, 2023
Is there any update on this issue? It's been a problem for a while, and I can not figure out how to use the CSS prop without manually adding the JSX Pragma in every file. It is extremely annoying to add it to every file and if anyone has a solution that does not involve prepending the pragma using a Webpack plugin it would be much appreciated! I am also using CRACO, but no luck getting it to work.
finnhvman commentedon Apr 16, 2023
Would be awesome to have an inline CSS solution out of the box. Svelte/SvelteKit does this the best way to my knowledge: no extra steps needed, you can just write standard CSS within your component and they are scoped to it by default, even the classes.
TamirCode commentedon May 31, 2023
I do not want to add
/** @jsxImportSource @emotion/react */at the top of every file in my CRA project. Not only because its extra work, and we as developers should find solutions for repetitive tasks, but also because it looks hideous and hacky.Does anyone have a step by step work-around this issue?
55Cancri commentedon May 31, 2023
Yes, the solution is simple: switch to vite yesterday and start using stitches instead of emotion. All your problems will be solved overnight.
TamirCode commentedon May 31, 2023
I like to use inline-styles like this, unfortunately stitches doesnt work like this.
TamirCode commentedon Jun 1, 2023
ive answered my own question here
https://stackoverflow.com/a/76381748/12671440
55Cancri commentedon Jun 1, 2023
Yes I used to write this way too. Now with stitches I can do:
The above is more of a kitchen sink example, but with stitches I can do your same stuff but use my own aliases for css properties AND values.
colsgets translated togridTemplateColumnsandmxexpands tomax-content.w,h,px, andbgbecomewidth,height,padding-leftandpadding-right, andbackground-colorunderneath._disabled,_active, and_hoverbecome&:disabled,&:active, and&:hover, respectively, but I could have made them anything I wanted.No more dealing with the limitations of CRA and emotion. I get to make my own CSS-in-JS shorthands. It's skyrocketed my UI development. Now I only use
cssprop to target child elements (andcssprop still works with stitches)I even added an
onLongPresshandler andcopyvariant to my button, and I have cool things for many of my components now. I have atruncateprop for my<Text>component (just a stitches createdptag underneath) that will apply at least 3 css classes to give me the ellipsis when text is too long. vite + stitches + framer motion + Radix colors has made all the difference.There is a little setup required but its so insanely worth it.
johannes-xerxes-sz commentedon Jan 18, 2024
Tried doing this and it works