nx
nx copied to clipboard
JS Libraries not working with expo
Current Behavior
Javascript libraries generated by npx nx g @nx/js:lib mylib
cannot be resolved in apps generated with nx generate @nrwl/expo:application my-app
.
Unable to resolve "@expo-workspace/mylib" from "src/app/App.tsx"
I want to share js libs between frontend & backend so creating an expo lib would not fit the use-case.
Expected Behavior
Functions exported by js libraries can be consumed in an expo project.
GitHub Repo
https://github.com/sem4phor/expo-jslib-bug
Steps to Reproduce
First 3 Steps can be skipped by using the reproduction repo.
- Follow https://nx.dev/packages/expo to create a new expo project (you might need to update the react-native version)
- generate a js library by following https://nx.dev/packages/js/generators/library (tsc build)
- import the function from the generated lib in
App.tsx
- Run
nx start my-app
- Press 'w' to open expo web
- See error in console
Nx Report
> NX Report complete - copy this into the issue template
Node : 16.13.1
OS : darwin arm64
npm : 8.3.0
Hasher : Native
nx : 16.3.2
@nx/js : 16.3.2
@nx/jest : 16.3.2
@nx/linter : 16.3.2
@nx/workspace : 16.3.2
@nx/detox : 16.3.2
@nx/devkit : 16.3.2
@nx/eslint-plugin : 16.3.2
@nx/expo : 16.3.2
@nx/react : 16.3.2
@nrwl/tao : 16.3.2
@nx/web : 16.3.2
@nx/webpack : 16.3.2
typescript : 5.0.4
---------------------------------------
Local workspace plugins:
@expo-workspace/mylib
Failure Logs
Web Bundling complete 116ms
› Open in the web browser...
› Press ? │ show all commands
Web Bundling failed 68ms
Unable to resolve "@expo-workspace/mylib" from "src/app/App.tsx"
› Stopped server
Operating System
- [X] macOS
- [ ] Linux
- [ ] Windows
- [ ] Other (Please specify)
Additional Information
Error goes away when removing package.json from my-lib (but then other code breaks. e.g. other js libs consuming these) OR adding main field to package json ("main": "src/index.ts")
i pushed up a pr to your repo: https://github.com/sem4phor/expo-jslib-bug/pull/1/files#diff-648b685b88a9c0026ac179c0753d8a4813a6a0f4deb4a4a34d714b46bfce1bb1 the issue is that you got a buildable expo library with package.json. when metro tries to resolve the library, instead of reading from tsconfig path, it tries to read from package.json. there is no main specified in package.json, it will go to index files in the package root. by adding a index under package will solve it.
or you can also add main the the package.json:
"main": "src/index.ts"
however, i still need to push up a proper fix for buildable expo libraries.
Diving a bit in the expo plugin code (node_modules/@nx/expo/plugins/with-nx-metro.js line 16-17
) I found following lines:
// Add support for paths specified by tsconfig
config.resolver = Object.assign(Object.assign({}, config.resolver), { resolveRequest: (0, metro_resolver_1.getResolveRequest)(extensions) });
which suggests that paths from tsconfig should resolve correctly. and as tsconfig base is extended i would expect that the paths resolve to the correct index files without the need of the extra index file 🤔
i turned on the debug verbose option, however, I realized this import did not even hit the metro resolver and did not hit the line below. I think the quickest workaround is just to add the index under the js lib root and re-export everything for this library. i think it might be related to metro? not sure whether upgrading metro would resolve this. let's see react native 0.72 would solve this.
Diving a bit in the expo plugin code (
node_modules/@nx/expo/plugins/with-nx-metro.js line 16-17
) I found following lines:// Add support for paths specified by tsconfig config.resolver = Object.assign(Object.assign({}, config.resolver), { resolveRequest: (0, metro_resolver_1.getResolveRequest)(extensions) });
which suggests that paths from tsconfig should resolve correctly. and as tsconfig base is extended i would expect that the paths resolve to the correct index files without the need of the extra index file 🤔
Thanks, was running into this issue. Adding the main value in package.json helped me get past the issue
If anyone is having a similar issue with NX 16 and @nx/expo 16:
What solved it for me was to make sure that when creating the library in nx, explicitly specify the nested directory "libs" using the option --directory=libs/<lib-name>
:
npx nx g @nx/expo:lib ui --directory=libs/ui --buildable
The option --buildable
may also be necessary, otherwise no build action is added (and no package.json is added).
As far as I can tell, the documentation either says nothing about 'libs' or it says it's just an option: https://nx.dev/concepts/more-concepts/applications-and-libraries - (A typical Nx workspace is structured into "apps" and "libs".) Nothing tells me it's required. As far as I can tell however, nx/expo seems to require it. Here is a script to reproduce a clean workspace with and without the libs folder. The one with works and the one without can't resolve. I have seen many issues raised related to metro being unable to resolve packages and I wonder if they could related to this or other idiosyncrasies like it. In any case, here is the script to reproduce from a clean workspace.
npx create-nx-workspace@latest broken-demo --preset=expo --nxCloud=false --appName=broken cd broken-demo npx nx g @nx/js:library broken-lib --unitTestRunner=none --bundler=tsc awk 'NR==14{print "import { brokenLib } from '''@broken-demo/broken-lib''';"}1' ./apps/broken/src/app/App.tsx > temp.txt && mv temp.txt ./apps/broken/src/app/App.tsx awk 'NR==34 {gsub("Broken", "{brokenLib()}"); print; next} 1' ./apps/broken/src/app/App.tsx > temp.txt && mv temp.txt ./apps/broken/src/app/App.tsx awk 'NR==8 {gsub("./src/index.js", "./src/index.ts"); print; next} 1' ./broken-lib/package.json > temp.txt && mv temp.txt ./broken-lib/package.json npx nx run broken:start cd ..
npx create-nx-workspace@latest working-demo --preset=expo --nxCloud=false --appName=working cd working-demo npx nx g @nx/js:library working-lib --unitTestRunner=none --bundler=tsc --directory=libs --projectNameAndRootFormat=derived awk 'NR==14{print "import { workingLib } from '''@working-demo/working-lib''';"}1' ./apps/working/src/app/App.tsx > temp.txt && mv temp.txt ./apps/working/src/app/App.tsx awk 'NR==34 {gsub("Working", "{workingLib()}"); print; next} 1' ./apps/working/src/app/App.tsx > temp.txt && mv temp.txt ./apps/working/src/app/App.tsx awk 'NR==8 {gsub("./src/index.js", "./src/index.ts"); print; next} 1' ./libs/working-lib/package.json > temp.txt && mv temp.txt ./libs/working-lib/package.json npx nx run working:start cd ..
This issue has been automatically marked as stale because it hasn't had any recent activity. It will be closed in 14 days if no further activity occurs. If we missed this issue please reply to keep it active. Thanks for being a part of the Nx community! 🙏
This issue has been closed for more than 30 days. If this issue is still occuring, please open a new issue with more recent context.