nrwl / nx

Smart Monorepos · Fast CI
https://nx.dev
MIT License
23.55k stars 2.35k forks source link

Cannot prebuild Expo app with brand new nx monorepo because Gradle `expo-modules-core` #26285

Closed guillempuche closed 4 months ago

guillempuche commented 5 months ago

Current Behavior

After creating a new expo monorepo with Nx v19.1.1, Gradle throws an error.

The only thing I updated is some Expo packages like @expo/cli, expo-dev-client...

Expected Behavior

Build the app locally on my Android emulator.

Haven't tested on iOS.

GitHub Repo

https://github.com/guillempuche/test-nx-expo

Steps to Reproduce

  1. Install packages with npm
  2. Change EAS config in app.json (username and EAS id)
  3. Run npx nx run expo:run-android

Nx Report

Node   : 20.9.0
OS     : darwin-arm64
npm    : 10.1.0

nx                 : 19.1.1
@nx/js             : 19.1.1
@nx/jest           : 19.1.1
@nx/linter         : 19.1.1
@nx/eslint         : 19.1.1
@nx/workspace      : 19.1.1
@nx/detox          : 19.1.1
@nx/devkit         : 19.1.1
@nx/eslint-plugin  : 19.1.1
@nx/expo           : 19.1.1
@nx/react          : 19.1.1
@nrwl/tao          : 19.1.1
@nx/web            : 19.1.1
@nx/webpack        : 19.1.1
typescript         : 5.4.5
---------------------------------------
Registered Plugins:
@nx/expo/plugin
@nx/eslint/plugin
@nx/jest/plugin
@nx/detox/plugin

Failure Logs

> nx run expo:run-android

› Installing using npm
> npm install

up to date, audited 1847 packages in 1s

238 packages are looking for funding
  run `npm fund` for details

7 moderate severity vulnerabilities

To address all issues (including breaking changes), run:
  npm audit fix --force

Run `npm audit` for details.
› Building app...
Configuration on demand is an incubating feature.

> Configure project :app
 ℹ️  Applying gradle plugin 'expo-dev-launcher-gradle-plugin' (expo-dev-launcher@4.0.16)

FAILURE: Build failed with an exception.

* Where:
Build file '/Users/guillem/programacio/codi/testing/test-nx-expo/node_modules/expo/android/build.gradle' line: 8

* What went wrong:
A problem occurred evaluating project ':expo'.
> Project with path ':expo-modules-core' could not be found in project ':expo'.

* Try:
> Run with --stacktrace option to get the stack trace.
> Run with --info or --debug option to get more log output.
> Run with --scan to get full insights.
> Get more help at https://help.gradle.org.

BUILD FAILED in 3s
10 actionable tasks: 1 executed, 9 up-to-date
Error: /Users/guillem/programacio/codi/testing/test-nx-expo/apps/expo/android/gradlew exited with non-zero code: 1
Error: /Users/guillem/programacio/codi/testing/test-nx-expo/apps/expo/android/gradlew exited with non-zero code: 1
    at ChildProcess.completionListener (/Users/guillem/programacio/codi/testing/test-nx-expo/node_modules/@expo/spawn-async/build/spawnAsync.js:52:23)
    at Object.onceWrapper (node:events:629:26)
    at ChildProcess.emit (node:events:514:28)
    at maybeClose (node:internal/child_process:1105:16)
    at ChildProcess._handle.onexit (node:internal/child_process:305:5)
    ...
    at Object.spawnAsync [as default] (/Users/guillem/programacio/codi/testing/test-nx-expo/node_modules/@expo/spawn-async/build/spawnAsync.js:17:21)
    at spawnGradleAsync (/Users/guillem/programacio/codi/testing/test-nx-expo/node_modules/@expo/cli/build/src/start/platforms/android/gradle.js:72:46)
    at Object.assembleAsync (/Users/guillem/programacio/codi/testing/test-nx-expo/node_modules/@expo/cli/build/src/start/platforms/android/gradle.js:52:18)
    at runAndroidAsync (/Users/guillem/programacio/codi/testing/test-nx-expo/node_modules/@expo/cli/build/src/run/android/runAndroidAsync.js:36:24)

 NX   1

——————————————————————————————————————————————————————————————————————————————————————————————————————————————————————

 NX   Ran target run-android for project expo (7s)

   ✖  1/1 failed
   ✔  0/1 succeeded [0 read from cache]

Package Manager Version

npm v10.1.0

Operating System

Additional Information

No response

milk717 commented 5 months ago

I'm experiencing the same problem. I'm using yarn workspace but I can't do android prebuild. The following error occurs.

Script '/Users/user/myProject-name/node_modules/expo-modules-core/android/ExpoModulesCorePlugin.gradle' line: 85

* * What went wrong:
A problem occurred configuring project ':expo'.
> Could not get unknown property 'release' for SoftwareComponent container of type org.gradle.api.internal.component.DefaultSoftwareComponentContainer.

Migrating the same project to a single repo rather than a monorepo will cause prebuild to operate normally. It runs well in the development phase because I looked at the https://docs.expo.dev/guides/monorepos/ document and set the appropriate metro.config setting and manual index.ts entry point.

But I can't just do prebuild. I've been suffering for three days. Does anyone know the solution??

FYI, I'm using the exposdk 51 version, but the same problem occurs with the sdk 50 version.

milk717 commented 5 months ago

Just fixed the Android prebuild issue!!!!!!! If you have the same problem as me, I think it will be solved in the following way

Why it didn't build

Error that occurred

> Configure project :expo
Evaluating project ':expo' using build file '/Users/user/WebstormProjects/healthcare-assistant-frontend/node_modules/expo/android/build.gradle'.
Using default execution profile
Starting process 'command 'node''. Working directory: /Users/user/WebstormProjects/healthcare-assistant-frontend/services/chatbot-app/android Command: node --print require.resolve('expo-modules-autolinking/package.json', { paths: [require.resolve('expo/package.json')] })
Successfully started process 'command 'node''
Using Kotlin Gradle Plugin gradle82 variant
Starting process 'command 'node''. Working directory: /Users/user/WebstormProjects/healthcare-assistant-frontend/node_modules/expo/android Command: node -e console.log(require('react-native/package.json').version);
Successfully started process 'command 'node''
Could not execute [report metric STATISTICS_COLLECT_METRICS_OVERHEAD]
Could not execute [report metric STATISTICS_COLLECT_METRICS_OVERHEAD]

FAILURE: Build completed with 2 failures.

1: Task failed with an exception.
-----------
* * Where:
Build file '/Users/user/WebstormProjects/healthcare-assistant-frontend/node_modules/expo/android/build.gradle' line: 17

* * What went wrong:
A problem occurred evaluating project ':expo'.
> Process 'command 'node'' finished with non-zero exit value 1

Expo gets the version of react-native by referring to react-native/package.json in node_modules in the prebuild process.

The phrase 'build.gradle' in that part is:

def getRNVersion() {
  def nodeModulesVersion = providers.exec {
    workingDir(projectDir)
    commandLine("node", "-e", "console.log(require('react-native/package.json').version);")
  }.standardOutput.asText.get().trim()

  def version = safeExtGet("reactNativeVersion", nodeModulesVersion)
  def coreVersion = version.split("-")[0]
  def (major, minor, patch) = coreVersion.tokenize('.').collect { it.toInteger() }

  return versionToNumber(
      major,
      minor,
      patch
  )
}

The version is being imported by setting workingDir to projectDir. However, in the current project, the dependencies related to Expo are installed on the root node_modules, while the dependencies related to react-native are installed on myproject-expo/node_modules. Therefore, it is expected that there was a problem getting the path. Work with morepos - Expo Documentation seems to have set up the environment assuming that the react-native package is installed on the root. Therefore, we fixed the problem by explicitly installing react-native on the root node_modules.

Why was the react-native dependency installed inside the package and not installed in root?

If you use Yarn Workspaces monorepo, most of the dependencies are hoisted and installed in the root node_modules. However, if different versions of the same dependencies are used in multiple workspaces, they are also installed in node_modules inside each package.

Yes) Package A uses the react 17 version, and Package B uses the react 18 version

If you look at react-native 0.74.1 package.json , react is fixed in the peerDependences part. However, the current version of react used in the myproject-web package is set to ^18, and accordingly, the latest version of react of 18 or later has been installed, and this version is 18.3.1. Therefore, the react-native version required by the react-native package is different from the version of react currently installed in the workspace, so react-native is installed as an individual dependency of the package, not the root. Currently the latest package.json in the react-native repository has changed peerDependencies to ^18.2.0, so the next version of react-native is likely to resolve this issue.

guillempuche commented 5 months ago

Fantastic @milk717! Thanks for the explanation, good learning for me. Waiting for the next release.

Expo and Nx is causing multiple problems explained here https://github.com/guillempuche/nx-expo-next-tamagui?tab=readme-ov-file#known-issues, and the benefit of using Expo CLI (yarn expo ..., npx expo ...). I'm splitting both worlds for now, https://github.com/guillempuche/nx-monorepo-with-expo-standalone-app.

xiongemi commented 4 months ago

i created a pr to your repo: https://github.com/guillempuche/test-nx-expo/pull/1

what I did:

guillempuche commented 4 months ago

Works like a charm @xiongemi with React Native 0.74.2 and Expo 51.

Hope the app's package.json will much cleaner after https://github.com/nrwl/nx/pull/26086.

For the rest of people, apart from some Android folder changes, Emily modified the package.json to:

{
  "name": "expo",
  "version": "0.0.1",
  "private": true,
  "dependencies": {
    "@testing-library/jest-native": "*",
    "@testing-library/react-native": "*",
    "metro-config": "*",
    "react-native": "*",
    "expo": "*",
    "react-native-svg": "*",
    "react-native-web": "*",
    "expo-dev-client": "~3.3.12",
    "react": "18.2.0",
    "expo-modules-core": "*",
    "expo-dev-launcher": "*",
    "expo-dev-menu": "*",
    "expo-json-menu": "*",
    "expo-json-utils": "*",
    "expo-manifests": "*",
    "expo-asset": "*",
    "expo-font": "*"
  },
  "scripts": {
    "eas-build-pre-install": "cd ../../ && node tools/scripts/eas-build-pre-install.mjs . apps/expo && cp package-lock.json apps/expo",
    "eas-build-post-install": "cd ../../ && node tools/scripts/eas-build-post-install.mjs . apps/expo",
    "android": "expo run:android",
    "ios": "expo run:ios"
  }
}

@xiongemi, how Expo CLI https://docs.expo.dev/more/expo-cli/ can work with Nx?

For example, Expo knows what dependency version to install for compatibility, npx expo install <expo_package>

github-actions[bot] commented 3 months ago

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.