-
-
Notifications
You must be signed in to change notification settings - Fork 29
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
Add support for jsx-runtime #129
Conversation
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #129 +/- ##
===========================================
- Coverage 100.00% 97.41% -2.59%
===========================================
Files 4 5 +1
Lines 964 1082 +118
===========================================
+ Hits 964 1054 +90
- Misses 0 28 +28 ☔ View full report in Codecov by Sentry. |
Hey, can you give more details about what and why you're doing this? |
For sure. Current statusIf you want to use this library in a typescript project you must use a tsconfig that looks something like this {
"compilerOptions": {
"jsx": "react",
"jsxFactory": "Html.createElement",
"jsxFragmentFactory": "Html.Fragment",
"plugins": [{ "name": "@kitajs/ts-html-plugin" }]
}
} the property "jsx": "react" tells typescript to substitute the jsx elements with a call to "Html.createElement" (or "Html.Fragment" in case there is a fragment). This implies that you have to have in your code a declaration of the Html object. The choice is to import it per file or globally using the module The catchWhen you choose the global import as a way to import the Html object you are going to encounter issues when you are trying to unit test your code (that uses jsx somewhere). This is because you have to import the "register module" on top of every unit test file. SolutionTypescript support "jsx": "react-jsx" that will transpile the jsx code with a call to a function called {
"compilerOptions": {
"jsx": "react-jsx",
"jsxImportSource": "@kitajs/html",
"plugins": [{ "name": "@kitajs/ts-html-plugin" }]
}
} code const a = <h1>Hello</h1> transpilled to something like const runtime = require('@kitajs/html/jsx-runtime')
const a = runtime.jsx('h1', { children: 'Hello' }) As you can see there is no global pollution and the import to the jsx function is made by the transpiler; removing the need to have a global import to The implementationI've followed the specification expected by typescript during the implementation of the jsx-runtime sub module. Hope this is clearer now, let's discuss about it! Docs: |
When importing other things from Reading more about |
README.md
Outdated
@@ -167,7 +182,8 @@ to generate HTML. Here are two options for importing the `@kitajs/html` package: | |||
``` | |||
|
|||
2. **Use the register to add a global namespace**: Import the `register` to globally | |||
register all necessary functions for convenience. | |||
register all necessary functions for convenience. You don't need to do that if you are | |||
using the `jsxImportSource` option in your `tsconfig.json`. |
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.
Should we prefer /register import or react-jsx
way of "globally" installing kitajs/html? I'm not sure if both would be good.
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.
I think that the best approach is to follow how preact do it https://preactjs.com/guide/v10/typescript/. They let the user choose how to configure Typescript between importing the h and Fragment functions into every file or using the "react-jsx" + "jsxImportSource" approach (automatic import done by the transpiler).
Side note here:
We should also consider adding some documentation on how to setup a project using babel or similar for non-typescript users.
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.
I'm up with you in this one. Let's remove /register
and only document manual import via jsx: react
or automatic import via jsx: react-jsx
.
I've seen I knew about |
Additionally, we could drastically improve kitajs/html performance with support for precompiling JSX. Read more: oven-sh/bun#6878 |
fd9a819
to
11b6a59
Compare
I don't think that this package need __jsxDEV because it does not have an actual need for it. The __jsxDEV is used to run checks during development on, for example, the fact that you are mapping elements without providing a key prop. Or other stuff like that. I had the same problem trying to create this first draft. The implementation that I did was against the tests using the alternative typescript config. There is a lot of React-related content on the topic of jsx on the internet but very little on "server side" jsx runtimes. I guess that we should start writing our stuff driven by trial and error. |
I'm on it |
It looks like this is still only supported in Deno + Preact, it's a good idea, but it won't be used by anyone until support arrives later in TS or in packagers. I created a proposal at microsoft/TypeScript#57468 for this, but I'm not sure if it will be accepted by the community... Until then, this feature will have to wait. |
We need to keep the same performance for |
I also simplified JSDoc comments for createElement functions, as their typings were wrong. |
With <div>{{a:1}}</div> // Previously was fine and was transformed to [object Object], which is unintended now: // ts(2353): Object literal may only specify known properties, and 'a' does not exist in type 'Promise<Children> | Children[]'
<div>{{a:1}}</div> Increasing even further the performance |
|
Current tasks:
|
@arthurfiorette let me know your thoughts about the deprecation message I add to the register module. Moreover, I think that adding the I will also add to the tasks:
I will handle the benchmarks now. |
I improved even further JSX/JSXS performance, using the average of kb/html and the time per iteration of our benchmarks, this is the result: Holy shit 1.2gbps I can finally rest in peace now XD. https://github.com/fastify/process-warning is a great example on how to deprecate things, so I followed their pattern (without installing it as a dependency). This is how it shows up on bun and nodejs: And this is what the user will see after clicking the link: I also added more examples to the serialization table. |
@JacopoPatroclo could you finish these two tasks below?
I think only using the correct way to deprecate it (process warning) is enough for now, let's see how the users react to it.
Awesome! |
@arthurfiorette I'm encountering issues migrating the benchmarks to use the new JSX-runtime. import { jsx as _jsx, jsxs as _jsxs } from '../../jsx-runtime' but as stated from the Node.js docs you can only import common-js modules using a "global import"
I've tried to convert everything to common-js but the package that we are using for benchmarking ( Side note, we should consider using pnpm-workspace to handle the benchmarks piece, it would be nice to reference the jsx-runtime using the real path ( Let me know what you think of my reasoning above and about the workspace approach. |
You could try to self install using a file path at {
"type": "module",
"dependencies": {
"kitajs": "file:.."
}
} Regarding the workspace approach, I'll probably create a workspace to group all html related projects into a single repository: https://github.com/kitajs/html But I do not have time for this now, maybe after this PR gets merged I can work on it. |
@arthurfiorette let me know if my refactoring of the project suits you. |
I can help with this task, I'm very familiar with Nx and pnpm workspaces. |
I've added changesets, before commiting any feature, please run |
Tasklist:
Regarding |
I've figured out the issue related |
@@ -11,7 +11,6 @@ it('Detect xss prone usage', async () => { | |||
<> | |||
<div> | |||
<div>{html}</div> | |||
<div>{object}</div> |
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.
@arthurfiorette I'm not sure about this, empty Objects are no longer supported by kitajs/html
, right? Should we live this line by adding an expected ts error or should we, as I did, remove the line completely?
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.
Hmm, but the error thrown in this line is not from the ts-html-plugin and just a type error from typescript.
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.
Yep, that's correct. So we should not test this behavior. I'll leave it like this.
For the love of god thank you!!! ts-server is a MAJOR pain. |
I'll review it asaic. In the meantime, this article have been sent to me regarding closing tags. Should we also remove it from kitajs/html? |
React still uses self closing tags, so let's just keep it in this way. |
I think were ready to merge. @JacopoPatroclo is there anything else missing? |
@arthurfiorette I think we should do a release candidate of the packages to test them inside some real projects. Just to make sure that they all are working properly. Can you manage to do that? I will test them on some of my projects as well. After that, we can close this PR. If you like I could add Nx to enable caching and task orchestration to the monorepo. Of course, I will do it in a separate PR. Is there a place where we can discuss stuff like this outside of PR's comments? |
Me too, I'll just merge this to main because the changeset is set up there...
Pnpm already does caching, task orchestration isn't needed for now as no complicated build step is required. Changesets already does releasing stuff too, so I think its enough for now. |
Anyways, thanks for the big effort you've put in here :) |
Yes, add me on discord: @arthurfiorette |
It would be nice to support the auto-import of the jsx runtime, removing the need to import the
@kitajs/html/register
sub-package.This PR aims to do that.
@arthurfiorette let me know if this seems like an improvement and if you would like to make this the standard way of configuring the tsconfig for this library. In that case, I will adapt the docs.