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

JSX Preserve Mode #6197

Open
mununki opened this issue Apr 24, 2023 · 13 comments
Open

JSX Preserve Mode #6197

mununki opened this issue Apr 24, 2023 · 13 comments
Assignees
Milestone

Comments

@mununki
Copy link
Member

mununki commented Apr 24, 2023

I would like to initiate a discussion on a potential feature: Preserve Mode for JSX expressions. The Preserve Mode is a functionality that, when enabled, maintains the original formatting and structure of JSX expressions in the JavaScript output generated by the compiler.

As the ReScript ecosystem evolves, it is worth exploring whether introducing Preserve Mode for JSX expressions to the compiler would be beneficial for the community. This feature could potentially enhance the readability and maintainability of the compiled output containing JSX, making it easier for developers to work with and understand the generated code. Another significant advantage of Preserve Mode is the possibility of using ReScript with frameworks like Preact and SolidJS, expanding the reach and applicability of the language.

Please share your thoughts and experiences regarding the necessity and potential benefits of implementing Preserve Mode for JSX expressions in the ReScript compiler. Do you think it is a valuable addition, or are there any concerns or technical challenges that might arise from its implementation?

@react.component
let make = () => {
  let (user, setUser) = React.Uncurried.useState(_ => "mununki")

  <div>
    <p> {`${user} uses ReScript`->React.string} </p>
    <input value=user onChange={e => setUser(._ => (e->JsxEventC.Form.target)["value"])} />
  </div>
}

preserved JSX

function Preserve(props) {
  var match = React.useState(function (param) {
    return "mununki";
  });
  var setUser = match[1];
  var user = match[0];
  return (
    <div>
      <p> user + " uses ReScript" </p>
      <input
        value={user}
        onChange={function (e) {
          setUser(function (param) {
            return e.target.value;
          });
        }}
      />
    </div>
  );
}
@mununki
Copy link
Member Author

mununki commented Apr 25, 2023

@cristianoc cristianoc added this to the v12 milestone Apr 26, 2023
@cornedor
Copy link
Contributor

Another significant advantage of Preserve Mode is the possibility of using ReScript with frameworks like Preact and SolidJS, expanding the reach and applicability of the language.

This would be very nice to have to build server side apps. The Bun JS runtime has built-in JSX support, and using libraries like https://github.com/nicojs/typed-html or https://github.com/kitajs/html you could render static HTML and serve it from the server without the need for more complicated SSR setups like Next.JS.

@zth
Copy link
Collaborator

zth commented Sep 17, 2023

@cornedor unrelated to this specific issue, but since you wrote this - I'm working on something like this, but without JSX preserve mode and just using ReScript's built in JSX support. Server side templating but with JSX and components like in React. Soon ready for alpha.

@Diogenesoftoronto
Copy link

I would love to see rescript be used with solidjs. If it's possible to get this done, I am willing to work on a PR if the maintainers are for it.

@texastoland
Copy link

Theoretically closed by #6565 (from announcement).

@mununki
Copy link
Member Author

mununki commented May 1, 2024

Theoretically closed by #6565 (from announcement).

I don't think it is. 😉 There will be cases where the generic transformation is not enough to solve.

@texastoland
Copy link

texastoland commented May 1, 2024

There will be cases where the generic transformation is not enough to solve.

Example would be helpful for others like me following 🙏🏼

@zth
Copy link
Collaborator

zth commented May 1, 2024

@texastoland for Solid the issue is that Solid ships their own Babel transform, that turns actual JSX into <template> tags. So while the generic JSX transform does allow us to bind to Solid h functions, those can't be transformed using their Babel transform, since that's looking for JSX specifically, and the JSX transform has already turned the ReScript JSX into actual function calls.

Hope that helps!

@cknitt
Copy link
Member

cknitt commented Oct 22, 2024

Preserve mode seems to be required for React Compiler (as of today at least).
See reactwg/react-compiler#22.

@cknitt cknitt changed the title Exploring the Need for Preserve Mode for JSX Expressions JSX Preserve Mode Oct 24, 2024
@nojaf
Copy link
Collaborator

nojaf commented Apr 9, 2025

I'm a bit stumped on how this could be implemented. To get started, I’m going to jot down some thoughts and questions:

Assuming you want to preserve the JSX, I would expect the ppx transform not to activate. This means that new Pexp_jsx_element would need to be carried through the type-checking phase. During that phase, we would still need to validate that props and children have the correct types.

After type-checking, some additional processes occur (optimizations, lambdas), but I assume nothing significant would happen there. Finally, we would print the typed JSX node back to JSX text in the js_printer.

@cristianoc, would that be more or less what needs to happen?

@zth
Copy link
Collaborator

zth commented Apr 9, 2025

Is there a way to annotate what's produced by the JSX transform so that we can follow it all the way to what actually emits this code:

JsxRuntime.jsx("div", {
  className: "123"
})

And then match on that to produce JSX instead of the function call?

@nojaf
Copy link
Collaborator

nojaf commented Apr 9, 2025

That feels a bit messy, as you transformed items only to transform them back later. Yes, we could potentially add an additional attribute to mark the JSX transform; however, I'm not sure this is necessary. It might also capture some React semantics that we may want to keep more agnostic.

@cristianoc
Copy link
Collaborator

cristianoc commented Apr 9, 2025

Whether the jsx transform can be moved to later phases in the compiler is a good question, I think.
Kind of a warm up question to what needs to be done for preserve mode anyway.
At least up to where type checking happens, there's no reason to perform the transform.
Branching after type checking makes sense, and I suspect might not require many changes to bring the jsx nodes all the way to the code generation.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Status: Backlog
Development

No branches or pull requests

8 participants