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

esbuild generates lowercase component name when jsx: "preserve" #1309

Closed
hzy opened this issue May 24, 2021 · 1 comment
Closed

esbuild generates lowercase component name when jsx: "preserve" #1309

hzy opened this issue May 24, 2021 · 1 comment

Comments

@hzy
Copy link

hzy commented May 24, 2021

We use esbuild (v0.12.1) as a bundler for a React component library. This means that we need to use the ability to preserve jsx. But when we enable this configuration, in the generated bundle, the JSXIdentifier of the React component starts with a lowercase letter. This will break subsequent build tools, including esbuild.

The following is a minimal output example, the directory structure can be seen from the comments generated by esbuild.

// ./node_modules/.bin/esbuild --bundle index.jsx --outdir=dist --jsx=preserve --external:react --format=esm

// index.jsx
import React2 from "react";

// components/a.jsx
import React from "react";
var A = class extends React.Component {
  render() {
    return <div />;
  }
};
var a_default = A;

// index.jsx
var App = class extends React2.Component {
  render() {
    return <a_default />;
  }
};
var blog_default = App;
export {
  blog_default as default
};

Pass the above bundle to esbuild again, the first parameter of the generated createElement function call is wrong.

  // ./node_modules/.bin/esbuild --bundle dist/index.js --loader:.js=jsx
  // ...
  var require_react = __commonJS({
    "node_modules/react/index.js"(exports, module) {
      "use strict";
      if (false) {
        module.exports = null;
      } else {
        module.exports = require_react_development();
      }
    }
  });

  // dist/index.js
  var import_react = __toModule(require_react());
  var import_react2 = __toModule(require_react());
  var A = class extends import_react2.default.Component {
    render() {
      return /* @__PURE__ */ import_react2.default.createElement("div", null);
    }
  };
  var App = class extends import_react.default.Component {
    render() {
      return /* @__PURE__ */ import_react2.default.createElement("a_default", null);
    }
  };
  var blog_default = App;

The expected behavior is that the JSXIdentifier of react components still starts with a capital letter, so that the subsequent build process will not be broken.

@evanw
Copy link
Owner

evanw commented May 25, 2021

Makes sense. I wish JSX didn't have this distinction because there's no way to pass an arbitrary expression as a tag. Although an alternative could be to use a local variable with a capital letter I suppose.

I think it should be possible to ensure that these variables continue to start with capital letters. However, this will have to be implemented twice (once for minifyIdentifiers: false and once for minifyIdentifiers: true) since minified name assignment is a different code path than name collision avoidance.

@evanw evanw closed this as completed in 7a0999e May 25, 2021
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

2 participants