-
Notifications
You must be signed in to change notification settings - Fork 455
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
[RFC] Generic JSX transform #6565
Conversation
How about |
Yes, that also works on this branch. |
Great work! I am wondering why it needs to be Can't one change the JSX config only and keep using |
We could make it configurable of course if this is a common approach. The Preact case is special in that people go between Preact and React. That's not the case of the rest of the potential integrations though. Solid JS, Vue, Hyperons, and more, are examples. It does sound like the case you're describing is better handled by just redefining |
that would be my 2 cents too, if you can have multiple jsx transforms in "jsx": {
"preact": "Preact",
"react": "MyCustomReact"
}, then it would make sense to have different annotations Otherwise I would stick to a generic |
Multiple transforms can't really be in the JSX config, you need to handle them in the local file. I don't have a strong opinion on what |
RFC updated to now not use dedicated @component like |
I updated the RFC again to remove the simplified |
8deb5ec
to
0e784ab
Compare
0e784ab
to
cdcd333
Compare
| Some i -> config.Jsx_common.version <- i); | ||
(match getString ~key:"module_" fields with |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The old mechanism didn't actually work, because module
is a reserved keyword.
I think we can move this forward in its current state. @cristianoc @mununki mind having a look at the code? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks great!
0bf8a9c
to
8fd987c
Compare
I'm checking this RFC out and have a problem with the Example: Custom jsx lib: {
"name": "reactor",
"namespace": "reactor",
"sources": [
{
"dir": "src",
"subdirs": true
}
],
"package-specs": [
{
"module": "es6",
"in-source": true
}
],
"suffix": ".mjs",
"bs-dependencies": [
"@rescript/core"
],
"bsc-flags": [
"-open RescriptCore"
],
"jsx": {
"module": "JSX"
}
} All the jsx stuff is implemented in Demo project: {
"name": "reactor-demo",
"sources": [
{
"dir": "src",
"subdirs": true
}
],
"package-specs": [
{
"module": "es6",
"in-source": true
}
],
"suffix": ".mjs",
"bs-dependencies": [
"@rescript/core",
"reactor"
],
"bsc-flags": [
"-open RescriptCore"
],
"jsx": {
"version": 4,
"mode": "automatic",
"module": "Reactor.JSX"
}
} When I build the demo, I get this error: "The module or file Reactor.JSX can't be found." Not totally sure if it was working before I added the namespace option. Before I outsourced the demo to another project, It was working fine. |
Good catch, I don't think we account for namespaces properly. Should be an easy fix. What else have you found in terms of issues? Would be good to try to squeeze in fixes in the next rc of 11.1. |
Some documentation stuff (s. https://forum.rescript-lang.org/t/rfc-generic-jsx-transform/5006/7?u=dkirchhof) Somewhere was written that you only need the |
This is a work in progress. Please feel free to give any feedback.
This generalizes the JSX (v4) transform to not only work on React, but any module that can fulfill the interface needed for the JSX transform.
Configuration
You configure a generic JSX transform by putting any module name in the
module
config of JSX. This can be any valid module name. So you can define your ownMyJsx.res
locally if you wanted to, and it'd still work. Example part fromrescript.json
:This will now put the
Preact
module in control of the generated JSX calls. ThePreact
module can be defined by anyone - locally in your project, or by a package. As long a it's available in the global scope. The JSX transform will delegate any JSX related code toPreact
.@react.component
will still be available, and so is a generic@jsx.component
notation. Both work the same way.One thing is important to note - the generic JSX transform has no
version
ormode
like the React JSX transform has. It's always JSX v4, and the mode is irrelevant (it'sautomatic
internally for the generic JSX transform). This doesn't matter for the generic JSX module, it only needs one implementation, but it's good to know.Usage example
Here's a quick usage example (the actual definition of
Preact.res
comes below):First, configure
rescript.json
:Now you can build Preact components:
And you can use them just like normal with JSX:
File level configuration
You can configure what JSX transform is used at the file level via
@@jsxConfig
, just like before. Like:Implementing a generic JSX transform module
Below is a full list of everything you need in a generic JSX transform module, including code comments to clarify. It's an example implementation of a
Preact
transform, so when doing this for other frameworks you'd of course adapt what you import from, and so on.As you can see, most of the things you'll want to implement will be copy paste from the above. But do note that everything needs to be there unless explicitly noted or the transform will fail.
Technical implementation
The technical implementation tries to minimize actual changes (since the React integration is still 1st class and the most refined one). The generic JSX transform is roughly implemented like this:
Outstanding questions
key
be available to all generic transforms? Is it needed?Future
Jsx.element
, which means that there's currently no true separation between different JSX at the type level. You could useReact.string
(because that returns aJsx.element
) interchangeably withPreact.string
(because that also needs to return aJsx.element
). This isn't ideal, but is pretty niche, so it's something we can solve later on.Wrapping up
Excited to hear your feedback on this! This will obviously need a bunch of documentation to be useful.
Personally, I'm excited to ship this even if it's in a reduced form because I believe it can unlock a bit of innovation in ReScript. One example is I'm building
res-x
that uses JSX on the server with ReScript as regular HTML templating. The JSX integration there will be much smoother and idiomatic with this generic JSX transform.