Running with expo canary
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
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.
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?
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
@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:
- I think you could simply re-export @stylexjs/postcss-plugin with default include merged under
packages/react-strict-dom/postcss-pluginorpackages/postcss-plugin. - 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?
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?
@javascripter PR for your suggestion would be appreciated if you have time. Thanks!
@lundn I had the same thought
@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"
@necolas Sent a PR to move the plugin to this repo.
@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)?
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
@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
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
@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.
https://github.com/expo/expo/pull/35520
Linking this PR as it seems relevant to the Uncaught TypeError: _interopRequireDefault is not a function. error .
@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 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.
Yeah let's leave this open until the updated expo setup is documented, and the babel bug is fixed (or a new issue)
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;