react-strict-dom icon indicating copy to clipboard operation
react-strict-dom copied to clipboard

Running with expo canary

Open stephenhandley opened this issue 11 months ago • 18 comments

Describe the issue

I've been trying to get react-strict-dom working with expo@canary and running into Uncaught TypeError: _interopRequireDefault is not a function.

Expected behavior

Hoping to be able to use react-strict-dom with Expo latest to port a web ui library which uses React 19 to work with Expo

Steps to reproduce

Here is a repo with the process I used and should be cloneable to quickly repro: https://github.com/stephenhandley/expo-rsd

As described there, I followed the process described here follow by the process in your docs

Test case

https://github.com/stephenhandley/expo-rsd

Additional comments

No response

stephenhandley avatar Mar 11 '25 01:03 stephenhandley

This is the stack trace:

Uncaught TypeError: _interopRequireDefault is not a function
    at HMRClient.ts:11:1
    at loadModuleImplementation (require.js:277:5)
    at guardedLoadModule (require.js:184:12)
    at metroRequire (require.js:92:7)
    at setupHMR.ts:1:1
    at loadModuleImplementation (require.js:277:5)
    at guardedLoadModule (require.js:184:12)
    at metroRequire (require.js:92:7)
    at effects.ts:8:5
    at loadModuleImplementation (require.js:277:5)

Your example doesn't even import RSD in any files that get bundled. I don't see anything pointing to RSD being the issue.

necolas avatar Mar 11 '25 01:03 necolas

The README.md on that repo describes things in more detail, maybe should have put it in this ticket.

Things work fine going through the canary setup until I follow the install process you're describing in your docs. The postcss and babel configs work fine but the metro.config.js causes the above error, this line in particular when uncommented, results in error/stacktrace I shared.

config.resolver.unstable_enablePackageExports = true;

I tried workarounds importing RSD components without that enabled but had no luck. Let me know if you would like more details there.

Here's the commit right before doing install process where things render fine with expo canary. https://github.com/stephenhandley/expo-rsd/commit/ad3ce6fe6ef912e02a85d0bfb7b46c423eadc5ce

Can you suggest any workarounds for the metro config?

stephenhandley avatar Mar 11 '25 03:03 stephenhandley

The README.md on that repo describes things in more detail, maybe should have put it in this ticket.

Yeah that would be a good idea. But thanks, that README explains the issue better.

I then get the following error

Web Bundling failed 2384ms index.js (326 modules)
 ERROR  stylex.css: ~/expo-rsd/node_modules/postcss-react-strict-dom/src/index.ts: `export = <value>;` is only supported when compiling modules to CommonJS.
Please consider using `export default <value>;`, or add @babel/plugin-transform-modules-commonjs to your Babel config.
  115 | plugin.postcss = true
  116 |
> 117 | export = plugin
      | ^^^^^^^^^^^^^^^
  118 |
› Detected a change in babel.config.js. Restart the server to see the new results. You may need to clear the bundler cache with the --clear flag for your changes to take effect.

@javascripter looks like the exports in the postcss plugin are a problem. Maybe we should move that plugin to this repo, so it's easier for us to keep up to date and patch.

If I comment out this line on metro.config.js the app will render, but then unsurprisingly can't import react-strict-dom components: config.resolver.unstable_enablePackageExports = true

Hmm, it's possible there's a regression in the Expo canary, if Metro changed. Let's see if @EvanBacon has any ideas. I'm not sure where Expo/Metro stands on support for package exports these days.

necolas avatar Mar 11 '25 03:03 necolas

@necolas

@javascripter looks like the exports in the postcss plugin are a problem. Maybe we should move that plugin to this repo, so it's easier for us to keep up to date and patch.

Yes, I don't mind moving the code over here. Currently, StyleX's official PostCSS Plugin basically mirrors my postcss-react-strict-dom repo with typescript code stripped out.

I see two options to proceed:

  1. I think you could simply re-export @stylexjs/postcss-plugin with default include merged under packages/react-strict-dom/postcss-plugin or packages/postcss-plugin.
  2. Or simply copy-paste from StyleX repo and maintain it here directly.

I think 1 is easier to maintain for now. Do you want me to create a PR or you can handle that yourself?

javascripter avatar Mar 11 '25 04:03 javascripter

I'm not sure if this is the case, but I suspect the error you're experiencing is related to the glob pattern used in your postcss.config.js. Both your application code and e.g config files exists on the same level. This mean all .js files (config files included) will be a part of the postcss processing.

Could you try to either move application code inside a top-level src folder or be more specific in the include / exlude options?

lundn avatar Mar 11 '25 12:03 lundn

@javascripter PR for your suggestion would be appreciated if you have time. Thanks!

@lundn I had the same thought

necolas avatar Mar 11 '25 16:03 necolas

@lundn thanks for the suggestion, had tried that previously with no luck wrt to the interopRequireDefault error. https://github.com/stephenhandley/expo-rsd/pull/2/files

However, went through the setup process again with a src dir and it does avoid the initial postcss export = plugin error. It didn't require installing @babel/plugin-transform-modules-commonjs.

Have cleaned things up to remove usage of that from the repro, also added the react-strict-dom import to demonstrate the error when unstable_enablePackageExports is off:

Web Bundling failed 1176ms src/index.js (324 modules)
Unable to resolve "react-strict-dom/runtime" from "src/App.js"

stephenhandley avatar Mar 11 '25 17:03 stephenhandley

@necolas Sent a PR to move the plugin to this repo.

javascripter avatar Mar 12 '25 09:03 javascripter

@stephenhandley @necolas I'm setting up a new monorepo with an Expo app (latest) in order to ask for help on another issue with RSD / StyleX / PostCSS. I quickly experienced the same issue as @stephenhandley has regarding config.resolver.unstable_enablePackageExports = true; resulting in Uncaught TypeError: _interopRequireDefault is not a function.

By chance I found an thread on Expo's discord mentioning that unstable_conditionNames seemed to fix a relating issue. I've not investigated why or how, but setting config.resolver.unstable_conditionNames = ["require", "default", "browser"]; in conjunction with unstable_enablePackageExports seems to fix the issue.

Do you have any thoughts (even though I understand this might not directly be a RSD issue)?

lundn avatar Mar 12 '25 10:03 lundn

My thoughts are that I wish Metro and Expo actually worked properly with modern packaging practices. Or at least documented what to do / stopped breaking frequently when people upgrade

necolas avatar Mar 12 '25 16:03 necolas

@lundn nice find, thank you! can verify this resolves the issue on my end.

I had missed that in the Metro documentation previously, but seeing now that it is mentioned here along with another experimental unstable_conditionsByPlatform flag: https://metrobundler.dev/docs/configuration/#unstable_conditionnames-experimental https://metrobundler.dev/docs/configuration/#unstable_conditionsbyplatform-experimental

stephenhandley avatar Mar 12 '25 19:03 stephenhandley

Still needs a lot of cleanup but have gotten the basics of things working with Expo+Next and a shared ui lib in a monorepo here: https://github.com/stephenhandley/expo-rsd

stephenhandley avatar Mar 13 '25 08:03 stephenhandley

@necolas @javascripter Ok have gotten things working but ran into a pretty curious bug in the process that figured would be of interest. More details here, but tldr is:

Apparently naming a local const variable (not exported) in a ui library component as defaultStyles:

// Do not name this variable "defaultStyles" 🤯
const defaultStyles = css.create({
  button: {
    padding: 4,
    color: 'white',
    backgroundColor: 'green',
    borderRadius: 4,
    borderWidth: 8,
    borderStyle: 'dashed',
    borderColor: '#00ff00',
    fontSize: 20,
  }
});

leads to a clobbering of those styles with an array of runtime__styles when this local ui package is being used in an Expo app package (did not see any similar issues with Next)

[
  {
    'runtime__styles.inlineblock': 'runtime__styles.inlineblock',
    borderStyle: 'borderStyle-x1y0btm7',
    margin: 'margin-x1ghz6dp',
    padding: 'padding-x1717udv',
    '$$css': true
  },
  {
    'runtime__styles.button': 'runtime__styles.button',
    borderWidth: 'borderWidth-xmkeg23',
    '$$css': true
  }
]

Renaming the variable to anything other than defaultStyles fixes things and then got what was expected

{
  'button__defaultStyles_NOPE.button': 'button__defaultStyles_NOPE.button',
  padding: 'padding-xfawy5m',
  color: 'color-x1awj2ng',
  backgroundColor: 'backgroundColor-x1u857p9',
  borderRadius: 'borderRadius-x12oqio5',
  borderWidth: 'borderWidth-x6h9yrm',
  borderStyle: 'borderStyle-xbsl7fq',
  borderColor: 'borderColor-x1657c11',
  fontSize: 'fontSize-xwsyq91',
  '$$css': true
}

my guess is one of these sections is involved in the collision: https://github.com/facebook/react-strict-dom/blob/a5bfc233609c25ca17884b26c5b32bb3ce7eec1d/packages/react-strict-dom/babel/plugin.js#L46-L50 https://github.com/facebook/react-strict-dom/blob/a5bfc233609c25ca17884b26c5b32bb3ce7eec1d/packages/react-strict-dom/babel/plugin.js#L56-L59

not sure how it plays in with postcss-react-strict-dom if at all. perhaps there's a scoping / namespacing approach to insulate against this happening.

stephenhandley avatar Mar 14 '25 01:03 stephenhandley

https://github.com/expo/expo/pull/35520 Linking this PR as it seems relevant to the Uncaught TypeError: _interopRequireDefault is not a function. error .

javascripter avatar Mar 18 '25 13:03 javascripter

@stephenhandley thanks, it looks like there is a bug in the babel plugin renaming - it should be avoiding collisions with local variable names but may not be given what you've experienced

necolas avatar Mar 18 '25 23:03 necolas

@necolas sure np, yeah sounds like there might be a collision, I've reached decent point where things are at on my end where we can close this if you'd prefer or if you wanna leave it open wrt that issue, happy to test fix in that repo later.

stephenhandley avatar Mar 20 '25 03:03 stephenhandley

Yeah let's leave this open until the updated expo setup is documented, and the babel bug is fixed (or a new issue)

necolas avatar Mar 20 '25 07:03 necolas

https://expo.dev/changelog/sdk-53-beta Expo SDK 53 beta has been released, and in my testing RSD runs fine both on native and web with the current documented setup. Only change is that we no longer need the below line as it's enable by default.

config.resolver.unstable_enablePackageExports = true;

javascripter avatar Apr 12 '25 18:04 javascripter