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

Custom react jsxImportSource output syntax #2704

Closed
awxalbert opened this issue Nov 28, 2022 · 7 comments
Closed

Custom react jsxImportSource output syntax #2704

awxalbert opened this issue Nov 28, 2022 · 7 comments

Comments

@awxalbert
Copy link

Quick question:
Is there a way to change the output import {} from 'react/jsx-runtime' to import {} from 'react/jsx-runtime.js

Background:
I wrote a lib which use jsx syntax internally, and I use tsup to bundle it to .js and .mjs files. Then I encountered this problem: facebook/create-react-app#11769 , which is a feature of mjs file according to this comment. And there are some solutions:

As a library author, I don't think either of them is a good alternative. I want to ship my package as soon as possible and cover the fix before delivered. Is there any workaround to achieve what I want? Thanks in advance.

@hyrious
Copy link

hyrious commented Nov 28, 2022

You can make that with the plugins api, use the onResolve hook to rename a path:

var fix_react_jsx_plugin = {
  name: "fix-react-jsx",
  setup({ onResolve }) {
    onResolve({ filter: /./ }, (args) => {
      if (args.path === "react/jsx-runtime") {
        return { path: args.path + ".js", external: true };
      }
    });
  },
};

@awxalbert
Copy link
Author

You can make that with the plugins api, use the onResolve hook to rename a path:

var fix_react_jsx_plugin = {
  name: "fix-react-jsx",
  setup({ onResolve }) {
    onResolve({ filter: /./ }, (args) => {
      if (args.path === "react/jsx-runtime") {
        return { path: args.path + ".js", external: true };
      }
    });
  },
};

Thanks but it's not the same thing actually. I don't write import {} from 'react/jsx-runtime in my code, it's esbuild that transpiles the jsx syntax and add import {} from 'react/jsx-runtime to the output, so the onResolve callback is not a right place to use.

@evanw
Copy link
Owner

evanw commented Nov 28, 2022

The React team has decided that these suffixes are part of the contract of the React-specific JSX transform. If you are using the React-specific JSX transform then you need to follow the contract. The React team are in control of how React works, so it's their decision to make. This is also in esbuild's documentation: https://esbuild.github.io/api/#jsx-import-source:

The /jsx-runtime and /jsx-dev-runtime subpaths are hard-coded by design and cannot be changed.

The community tried doing what you suggested, but it broke things and was reverted:

So I'm not going to add this to esbuild. As a library author, the way to fix this is to use the exports field to map the /jsx-runtime and /jsx-dev-runtime subpaths to whatever you need them to be. Either that or you can use the original JSX transform which doesn't have these subpath requirements.

@evanw evanw closed this as not planned Won't fix, can't repro, duplicate, stale Nov 28, 2022
@awxalbert
Copy link
Author

@evanw Thanks for the reply. I understand neither esbuild or babel should add .js suffix to the import syntax, what I want to achieve is like what @hyrious said, just an entry to manipulate the out of the esbuild, I just don't know the right way to do.(maybe by plugin?).

I learned about the exports key, but it seems it's not useful in my case, it only creates a map of my package's export, not a map of my package's internal import. Say I wrote pkg-a, and the code is as below:

export const Dummy = () => {
  return <div>text</div>;
};

When I bundle it by esbuild, the output would be:

import { jsx } from "react/jsx-runtime";
var Dummy = () => {
  return /* @__PURE__ */ jsx("div", {
    children: "text"
  });
};

When I use pkg-a in an app, the exports only works when I require subpaths of pkg-a, right? This way it doesn't solve the problem.

import { Dummy } from 'pkg-a/xxx'

@evanw
Copy link
Owner

evanw commented Nov 29, 2022

I learned about the exports key, but it seems it's not useful in my case, it only creates a map of my package's export, not a map of my package's internal import.

I'm still not quite sure what your use case is, but it's worth mentioning that node has a corresponding imports field too (if the package is trying to internally import from itself). I haven't tested that with this form of JSX but it might work.

@awxalbert
Copy link
Author

I'm still not quite sure what your use case is, but it's worth mentioning that node has a corresponding imports field too (if the package is trying to internally import from itself). I haven't tested that with this form of JSX but it might work.

I'll create a repo to illustrate later.

@awxalbert
Copy link
Author

Hi @evanw , sorry for the delay, I created a demo.

And here is the case, when you run yarn build, you will see the output of this library in mjs format as following:

// src/index.tsx
import { jsx } from "react/jsx-runtime";
var Demo = (props) => {
  return /* @__PURE__ */ jsx("div", { className: "Demo", children: "text" });
};
export {
  Demo
};

And all I want to achieve is that append a js suffix to the first line in output

- import { jsx } from "react/jsx-runtime";
+ import { jsx } from "react/jsx-runtime.js";

Then if others use my package, they don't even need to think about this issue we discussed above, I'll handle it under the hood.

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

No branches or pull requests

3 participants