Repository navigation
JSX Support #56822
Description
What is the problem this feature will solve?
Following up on nodejs/node#56322 and nodejs/node#56392.
JSX and its various flavors have undergone frequent configuration changes since their inception. While supporting JSX without any configuration might seem ideal, it is both impractical and problematic. Just as "type": "module" was introduced to address CommonJS/ESM interoperability, we must continue relying on existing configuration files—tsconfig.json or jsconfig.json—to determine the correct transformation to apply.
The presence or absence of JSX should not rely on node's recent work for supporting typescript.
JSX has multiple targets, primarily react and react-jsx, which produce different outputs from the same input. For example:
<h1>Hello world</h1>-
react-jsximport { jsx as _jsx } from "react/jsx-runtime"; _jsx("h1", { children: "Hello world" });
-
reactOutputimport React from "react"; React.createElement("h1", null, "Hello world");
-
jsxFactory– Specifies the function to replacecreateElementwhen using thereacttarget. For example, settingjsxFactory: 'h'replacesReact.createElementwithh. -
jsxFragmentFactory– Determines the function used for fragments (<></>). If set, fragments will use the specified name instead ofReact.Fragment. -
jsxImportSource– Used with thereact-jsxtarget to change the import source. For example, settingjsxImportSource: 'preact'results in:import { jsx as _jsx } from "preact/jsx-runtime";
Their combination is what is needed for any library that supports JSX, such as Vue.js, Kita, React, Preact, Astro, and others...
Given the diversity of JavaScript frameworks, adopting a default configuration favoring any single framework would inevitably create issues for others.
One alternative is to add fields to package.json to define some JSX settings, eliminating the need for a jsconfig.json or tsconfig.json file. However, rewriting this (ideal or not) standard is not something the community will like.
In the long run, adding support for a native JSX transform function, similar to Deno’s implementation, could significantly enhance Node.js performance in SSR scenarios.
Deno's native transform has demonstrated 7-20× faster rendering times and 50% reduction in garbage collection overhead. Such improvements would benefit SSR frameworks like Next.js, positioning Node.js competitively once again.
What is the feature you are proposing to solve the problem?
I propose that nodejs transform JSX syntax and support .jsx and .tsx files.
What alternatives have you considered?
No response
Metadata
Metadata
Assignees
Labels
Type
Projects
- StatusShow more project fieldsAwaiting Triage
Activity
marco-ippolito commentedon Jan 30, 2025
I was exploring this idea.
We could create a hook that framework can implement.
Example
Every frameworks can do something like:
Is transpiled into:
ljharb commentedon Jan 30, 2025
What happens when there's more than one hook registered in an application, as would be virtually guaranteed to happen?
There's a reason jsx isn't in the language yet, or in any platform.
marco-ippolito commentedon Jan 30, 2025
Care to explain why?
Also
Expand pls
ljharb commentedon Jan 30, 2025
What I mean is, the rules for the syntax are pretty universal and clear - the problem is that there's a plethora of transformations of it. If you had to pick only one, you'd pick React's - but which one? The pre-17 one, that's way more widely used, or the 17+ one, that's the future of React?
If you only pick one, then you ace out anyone using an alternative transformation.
If you allow it to be customizable, and it's not customizable per module (which would require syntax, for ESM, and thus TC39 support - although with CJS you could do it by just injecting a new function into scope), then you've created a global state and capability that means that any code that can set it, can override the meaning of what appears to be syntax - which is a massive security hole and attack vector.
In other words, I think that the only way to support jsx that's even remotely reasonable here is with a loader, and users can already use custom loaders to achieve it - so "node supports jsx" would just mean that node ships a loader by default, which would mean node is picking a winner - and, if node's picking a winner, per the usage data, it's going to be React, and that's not exactly fair to React competitors.
There may come a time in the future when the JS language can answer some of these questions - or when userland has largely settled on a single jsx transformation - but until that time, it feels at best incredibly risky and worst the precursor to an abject disaster for node to attempt to address this itself.
marco-ippolito commentedon Jan 30, 2025
@ljharb I understand the technical issues, but I don't agree with marking a problem as "won't fix" without exploring it. This has been one major historical problem of the loaders space, which has burned out several people. While I understand its not an easy fix, it would be more useful to talk about blockers and requirements for this to happen. The jsx support is something that can be fixed, just like typescript support, and we shoud look into fixing it
arthurfiorette commentedon Jan 30, 2025
A single transformation target is not what JSX needs.
Any attempt to standardize it into a single format seems prone to failure. JSX community has already proven different syntaxes are better for different use cases:
jsx: react-jsxprefers a importable module following some rules.jsx: reactrequiresReactto be available in local scope, the following code is valid:And that's part of how JSX is supposed to be.
ljharb commentedon Jan 30, 2025
exactly. And when there’s multiple valid ways of handling a syntax, the existing solution for that is “custom loaders”.
koshic commentedon Jan 30, 2025
Those arguments are 100% applicable to TypeScript support too. But, Node.js team finally decided to choose one option (SWC in amaro) and implement basic support level keeping hooks only for advanced scenarios. What is the difference between JSX and TS? Both can be compiled by various ways, both can have overcomplicated external configuration, both are tightly coupled with 3rd-party ecosystem, etc.
JSX / TS / support in Node.js just a step towards the community, because base framework functionality more than enough to implement any possible solution by using third-party tools / libraries / even native addons.
What I want to say - JSX support is mostly not a technical question. May be it's need to have TSC decision or something like that.
ljharb commentedon Jan 30, 2025
I'm not aware of an alternative semantic meaning for compiled TS output - it's JavaScript. Babel, tsc, swc, all compile TS with different approaches that result in the same runtime JS. JSX is vastly different, and the various approaches result in widely varying runtime behavior.
marco-ippolito commentedon Jan 30, 2025
it is possible to standardize the transpilation to a certain point and have the framework hook in with some Node API. We probably should ask framework maintainers.
For example:
is transpiled to:
The framework can register a hook to do something with the object that is passed:
{ tag: 'div' }koshic commentedon Jan 30, 2025
It's not quite true - generated code is different even for the one particular tool.
For example, tsc has a lot of flags that directly affect JS output: preserveConstEnums, downlevelIteration, importHelpers, noUncheckedSideEffectImports, esModuleInterop, verbatimModuleSyntax, importsNotUsedAsValues, preserveValueImports, etc.
SWC has even more. This is why current state of TS support in Node is a compromise with some defaults and this is why we have 'Full TypeScript support' chapter in the documentation.
ljharb commentedon Jan 30, 2025
That is indeed how it could technically be achieved - but then we've got global state (the current JSX handler) and apps could have multiple JSX transpilations in the same application, even ignoring third party dependencies.
10 remaining items
github-actions commentedon Dec 6, 2025
There has been no activity on this feature request for 5 months. To help maintain relevant open issues, please add the never-staleIssues and PRs exempt from automated stale handling.
label or close this issue if it should be closed. If not, the issue will be automatically closed 6 months after the last non-automated comment.
For more information on how the project manages feature requests, please consult the feature request management document.
arthurfiorette commentedon Dec 8, 2025
JSX is part of today's ecosystem. JSX being framework agnostic implies that multiple stuff might be using jsx at the same time. People can use it to render xml, html strings, email templates and anything else they ever want. Even if big frameworks will need to keep transpiling JSX in the future, not a problem! Still, Implementing native support brings simple use-cases much more compelling to the scene.
The same way TS support was added for simplicity, since it was possible to run TS code before and a lot of people will keep using transpilers in their process of running TS code in the future, JSX should be handled the same way.
Specially now that we have amaro set up and, besides settling down on settings/DX, this should not be as hard as it was to set up TS support in the first place.
mertcanaltin commentedon Dec 28, 2025
Hello, I tried to make a plan regarding this place What do you think?
My plan:
Add
--experimental-jsxflag,Use amaro (already supports JSX via SWC),
Read config from
tsconfig.json/jsconfig.json,Default to
react-jsxtransform,Support per-file
/** @jsxImportSource */pragmaUpdate: I discussed this with @marco-ippolito on Slack and understand the concerns:
Thanks for the feedback everyone!
AugustinMauroy commentedon Dec 28, 2025
I don't see how to include JSX support how of the box to node.js
imo the official answer should be use customization api.
ljharb commentedon Dec 28, 2025
While I'd love to see node support jsx, I think that until it is a standard, it wouldn't make much sense.
AugustinMauroy commentedon Dec 28, 2025
meta already write something https://facebook.github.io/jsx/ we use that as basis of a real thing. Maybe open an issue at CPC to create an openjs wg
bjohansebas commentedon Dec 28, 2025
The standards group is already, which could presumably handle making it a standard on behalf of OpenJS.
ljharb commentedon Dec 28, 2025
That's only the syntax - it doesn't talk about the transformation itself, which is why every tool that works with JS makes up their own (and even React changed it in v17). A transformation would have to be designed, agreed upon, and adopted across existing tools, before it would make sense for anyone to try to standardize JSX.
Renegade334 commentedon Mar 3, 2026
--experimental-transform-typesis being removed, for reasons outlined in nodejs/typescript#51. I cannot see that the same arguments would not apply to an amaro-based JSX transformer.For my $0.02, this and #56822 (comment) are enough to make this wontfix.
AugustinMauroy commentedon Mar 3, 2026
agreed that we can close for people who want to run JSX on nodejs without building process they can still use customization hooks
github-actions commentedon Jul 20, 2026
This issue has been marked as stale due to 90 days of inactivity.
It will be automatically closed in 30 days if no further activity occurs. If this is still relevant, please leave a comment or update it to keep it open.