[Feat] Support new jsx - jsx-runtime
What problem does this feature solve?
Same feature issue in Vue2 https://github.com/vuejs/vue/issues/12379.
See https://babeljs.io/docs/en/babel-plugin-transform-react-jsx for more details.
We can have a better JSX experience.
Even we can process all the directives/ref/slot features with vue/jsx functions.
Transform original jsx(...)
input to vue.h(...)
What does the proposed API look like?
In:
/** @jsxImportSource vue */
const profile = (
<div>
<img src="avatar.png" class="profile" />
<h3>{[user.firstName, user.lastName].join(" ")}</h3>
</div>
)
Out:
import { jsx as _jsx } from "vue/jsx-runtime";
import { jsxs as _jsxs } from "vue/jsx-runtime";
const profile = _jsxs("div", {
children: [
_jsx("img", {
src: "avatar.png",
class: "profile",
}),
_jsx("h3", {
children: [user.firstName, user.lastName].join(" "),
}),
],
});
Don't use the React JSX transform for Vue... they are not the same.
For Vue 3 you should be using https://github.com/vuejs/jsx-next
@yyx990803
The repo
I created a repo for support JSX runtime vue-jsx-runtime and examples vue-jsx-runtime-examples.
Runtime size:
- minify Iife:
2.53Kb
(no gzip) - ES Module: 8.79kb (no minify)
About examples( used TS):
Different with vue jsx-next
jsx-next
is a plugin forBabel
only.vue-jsx-runtime
can be used withBabel
,TypeScript
,swc
,esbuild
and more.
vue-jsx-runtime
limits:
- can not merge ele/component props
v-model
syntax is little different withjsx-next
-v-model
First of all
We should forget the react
xx, something like babel-plugin-transform-react-jsx
. Maybe babel and other tools can be renamed to other name, like: jsx-runtime
. 😆
The advantages
- "Standard" JSX supported, runtime jsx. It can be used with
Babel
,TypeScript
,swc
,esbuild
and more... - Runtime transform JSX ast to vue
render()
. Simple and easy to extend and maintain - Maybe we can share transform logic with
compile-core
andcompile-dom
in the future
@yyx990803 react-jsx
just make a way to let us to define any jsx not just react
Once vue provider exports vue/jsx-runtime
and vue/jsx-dev-runtime
,
We could easy to make use to use vue jsx with current build tools typescript/esbuild/swc
, not only babel
.
Just with options "jsx": "react-jsx"
and "jsxImportSource": "vue"
If you don't want rewrite too much, we could just wrap h
instead.
Howerver, hope it could do some refactor.
Because the key
logic is different, more context https://github.com/facebook/react/issues/20031
// vue/jsx-runtime.ts
export const jsxs = (type: any, { children, ...otherProps }: any = {}, key: string | undefined) => {
const props = key ? { ...otherProps, key } : otherProps;
if (typeof type === "object") {
return h(type, props, isProxy(children) ? children : () => children);
}
return h(type, props, children);
};
export const jsx = (type: any, { children, ...otherProps }: any = {}, key: string | undefined) => {
const props = key ? { ...otherProps, key } : otherProps;
if (children) {
if (typeof type === "object") {
return h(type, props, isProxy(children) ? children : () => children);
}
return h(type, props, children);
}
return h(type, props);
};
// vue/jsx-dev-runtime.ts
import { Fragment } from "vue";
import { jsx, jsxs } from "./jsx-runtime";
export { Fragment };
export function jsxDEV(
type: any,
props: any = {},
key: string | undefined,
_isStaticChildren: boolean,
_source: object,
_self: object
) {
if (Array.isArray(props.children)) {
return jsxs(type, props, key);
}
return jsx(type, props, key);
}
{
"exports": {
"./jsx-runtime": {
"import": {
"types": "./jsx-runtime.d.ts",
"default": "./jsx-runtime.mjs"
}
},
"./jsx-dev-runtime": {
"import": {
"types": "./jsx-dev-runtime.d.ts",
"default": "./jsx-dev-runtime.mjs"
}
}
},
}