resium icon indicating copy to clipboard operation
resium copied to clipboard

Always use automatic jsx transform

Open ls-yannick opened this issue 2 years ago • 0 comments

Heya! First of all, thank you for maintaining resium! We've used it in a couple of prototypes and it has worked out well for us, and we are looking forward to using it more.

We have run into a small problem with our latest project. While the proposed change fixes our problem, I can't say I fully understand what is happening. Here is the situation:

  • We are building a js library that among other things offers cesium visualizations.
  • Just like resium, our library is compiled using vite in library mode. cesium, react and react-dom are also treated as externals and are provided by host applications. Our configurations are exactly the same in that regard.
  • We use the react vite plugin without custom options, and by default is uses the automatic jsx transform
  • When we package our library, the resium.mjs file is transformed again by vite (which seems normal to me)

This is where things get interesting.

classic transform

We get the following error when using our library: ReferenceError: React is not defined. It traces back to this line in resium but I believe it's unrelated to the line itself, it's just that this is the first call to a React function when we are using resium.

In resium.mjs, the output is as follows

import k, { createContext as ge, etc… } from "react";

return h ? /* @__PURE__ */ k.createElement(x.Provider, {
      value: h
    }, s) : s;

and inside our library compiled code

import React__default from "react";
…
return h2 ? /* @__PURE__ */ React.createElement(x$2.Provider, {
      value: h2
    }, s2) : s2;

Note that k.createElement gets transformed into React.createElement — but React is not present in the global scope.

automatic transform

If resium uses automatic transform mode (eg. what this PR proposes), the output is

In resium.mjs

import ai, { createContext as Gi, etc } from "react";
…
return E ? /* @__PURE__ */ le(Le.Provider, {
      value: E,
      children: f
    }) : f;

Note that it uses le and not ai. le in the compiled source points to the react jsx transformed that is now shipped along.

In our library

import React__default from "react";
…
React__default.createElement(me$1.Provider…

The code is transformed again, but this time the resium dependency to react is treated like all the others we have in our code, it gets mapped to an import from "react", and the host application will have to deal with that since it's a dev dependency.


In summary, I think this is an edge case where if resium is compiled again in a context where react is not present (because it's an external), the classic transform mode has as consequence that resium expect React to be present as a global variable, as a fallback. With the new automatic transformer this is not the case. While I'm confident that the PR fixes our issue, I don't know what other consequences it could have, especially on the umd version of the package.

Was there any specific reason to use the classic transformer for production?

ls-yannick avatar Sep 19 '22 14:09 ls-yannick