Skip to content

Comments

Fix CLI_PATH resolution when @expo/cli is nested inside expo/node_modules#85

Open
pkelecom wants to merge 1 commit intobndkt:mainfrom
pkelecom:fix-cli-path-resolution
Open

Fix CLI_PATH resolution when @expo/cli is nested inside expo/node_modules#85
pkelecom wants to merge 1 commit intobndkt:mainfrom
pkelecom:fix-cli-path-resolution

Conversation

@pkelecom
Copy link

Problem

In projects using Expo SDK 50+, @expo/cli is no longer hoisted to the root node_modules — it lives inside expo/node_modules/@expo/cli. The App Clip bundle phase script used require.resolve('@expo/cli') which fails with:

Error: Cannot find module '@expo/cli'

This causes the build to silently fall back to the legacy React Native bundler (react-native-xcode.sh with its own CLI), which doesn't understand path aliases like @/ imports configured via Metro. The result is a confusing secondary error:

UnableToResolveError: Unable to resolve module @/utils/SomeHelper

Fix

Use the same resolution strategy that Expo already generates for the main app target — passing a paths option so Node can find @expo/cli relative to the expo package, regardless of hoisting:

Before:

export CLI_PATH="$("$NODE_BINARY" --print "require.resolve('@expo/cli')")"

After:

export CLI_PATH="$("$NODE_BINARY" --print "require.resolve('@expo/cli', { paths: [require.resolve('expo/package.json')] })")"

Impact

This affects any project using react-native-app-clip with Expo SDK 50+ that does not have @expo/cli listed as a direct dependency in package.json. The fix is consistent with how Expo itself resolves the CLI in the main target's bundle phase.

Made with Cursor

…ules

In projects using Expo SDK 50+, @expo/cli is no longer installed at the
root node_modules level — it lives inside expo/node_modules/@expo/cli.
The previous require.resolve('@expo/cli') call fails with
"Cannot find module '@expo/cli'", causing the App Clip bundle phase to
fall back to the legacy React Native bundler which lacks support for path
aliases (e.g. @/ imports).

This uses the same resolution strategy that Expo already generates for
the main app target: passing a paths option so Node resolves @expo/cli
relative to the expo package, regardless of hoisting.

Before:
  export CLI_PATH="$($NODE_BINARY --print "require.resolve('@expo/cli')")"

After: export CLI_PATH="$($NODE_BINARY --print "require.resolve('@expo/cli', { paths: [require.resolve('expo/package.json')] })")"
Co-authored-by: Cursor <cursoragent@cursor.com>
@nathan-ahn
Copy link
Collaborator

@pkelecom Could you clarify which Expo version and package installer you're encountering this issue on?

Additionally, I believe the proposed fix here may cause breaking changes depending on hoisting behavior.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants