Subscribe on changes!

[Feat] Support new jsx - jsx-runtime

avatar
Dec 10th 2021

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(" "),
    }),
  ],
});
avatar
Dec 10th 2021

I don't quite get your meaning, we already have jsx-next, what is the different?

avatar
Dec 10th 2021

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

avatar
Dec 14th 2021

@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 for Babel only.
  • vue-jsx-runtime can be used with Babel, TypeScript, swc, esbuild and more.

vue-jsx-runtime limits:

  • can not merge ele/component props
  • v-model syntax is little different with jsx-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 and compile-dom in the future
avatar
Mar 24th 2023

@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"
      }
    }
  },
}