Skip to content

Commit

Permalink
feat: improve monorepo support by removing redundant PROJECT_ROOT (#2…
Browse files Browse the repository at this point in the history
…8354)

Summary:
Historically, React Native didn't support a lot of custom project structures apart from the standard flat directory with `ios` and `android` folders. The CLI had to be explicitly started from the project root, otherwise Metro didn't work right.

In order to resolve the project root in the most accurate way, React Native assumed that project root is always `../../` from its location in `node_modules` - this is not true when the installation gets hoisted (e.g. in a monorepo).

To address that, janicduplessis brought support for custom [`PROJECT_ROOT`](9ccde37) that allowed overriding the `../../` in case it wasn't true.

Today, CLI is able to automatically resolve the project root, no matter where it's started. It will traverse the tree of the directories upwards and stop as soon as it meets `package.json`.

As a result, it doesn't really matter from where we start the CLI anymore as a part of `react-native-xcode.sh`.

By replacing the default value of `$REACT_NATIVE_DIR/../../` with `$PWD, that is default for all Xcode scripts, we can make the setup for monorepo easier - nobody will need to set `$PROJECT_ROOT` in order to override the incorrect defaults.

By default, all scripts defined in Xcode run from `$PWD` directory, which is the location of the iOS project. In the future, we will be able to remove `cd` entirely.

To better understand this PR, let's look a few hypothetical structures as an example:

#### Monorepo:

> tl;dr works out of the box, no need to mess around with paths

```
- package.json
- packages/
  - my-app/
     - index.js
     - package.json
     - ios/
        - MyApp.xcodeproj
```

**Before this PR**, the `react-native-xcode.sh` will start the CLI like this:

```bash
cd $REACT_NATIVE_DIR/../../
node <absolute_path_to_cli.js> bundle --entry-point index.js
```

- Because we change the directory to the root of monorepo, CLI throws an error. All in all, there's no `react-native` dependency at the workspace root.

- Some users turn `no hoist` in an act of troubleshooting the errors, which resolves the problem - `react-native` is moved under `my-app/node_modules` which makes this mechanism resolve properly.

- Some users find out about `PROJECT_ROOT` and set it to overwrite the default value. For example, setting `export PROJECT_ROOT = "$PWD/../` will set the directory to `my-app`, which has a dependency on `react-native` in a `package.json` and makes the CLI happy.

**After this PR**, the `react-native-xcode.sh` will start the CLI like this:

```bash
cd $PWD
node <absolute_path_to_cli.js> bundle --entry-point index.js
```

- The `$PWD` is `packages/my-app/ios/` because that's where the Xcode project is located. CLI will automatically set the root to `../` because that's where it finds `package.json` with `react-native` dependency. It will pass that root to Metro, unless users have set a different one themselves. Thanks to that, all paths to JavaScript files remain working and unaffected.

- No need to set `PROJECT_ROOT` anymore.

- We don't rely on the location of `node_modules`, which is cleaner and future proof.

#### Standard:

> tl;dr no changes

```
- ios/
   - MyApp.xcodeproj
- index.js
- package.json
```

**Before this PR**, the `react-native-xcode.sh` will start the CLI like this:

```bash
cd $REACT_NATIVE_DIR/../../
node <absolute_path_to_cli.js> bundle --entry-point index.js
```

- Everything works fine. Path from `react-native` inside `node_modules` is correct - the project root is set right to `/`

**After this PR**, the `react-native-xcode.sh` will start the CLI like this:

```bash
cd $PWD
node <absolute_path_to_cli.js> bundle --entry-point index.js
```

- The root will be set to where Xcode project is located, which is `/ios`. This is the PWD for all Xcode scripts.

CLI will look for the `package.json` going upwards from `ios` folder. Will stop at `/`, find out it has `react-native` dependency, load it and its commands and proceed further.

## Changelog

[iOS] [Feature] - Better monorepo support when building release apk
Pull Request resolved: #28354

Test Plan:
- All projects (standard/monorepo) run without issues.
- PROJECT_ROOT is not needed.

CC: Titozzz (who wrote monorepo guide), alloy, bartolkaruza

Reviewed By: cpojer

Differential Revision: D20558005

Pulled By: hramos

fbshipit-source-id: 2551120beadcfd4c2f1393ce8a2c2fa6b93c9290
  • Loading branch information
grabbou authored and facebook-github-bot committed Mar 20, 2020
1 parent 175589b commit a8e8502
Showing 1 changed file with 14 additions and 5 deletions.
19 changes: 14 additions & 5 deletions scripts/react-native-xcode.sh
Original file line number Diff line number Diff line change
Expand Up @@ -54,11 +54,17 @@ case "$CONFIGURATION" in
;;
esac

# Path to react-native folder inside node_modules
REACT_NATIVE_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
# The project should be located next to where react-native is installed
# in node_modules.
PROJECT_ROOT=${PROJECT_ROOT:-"$REACT_NATIVE_DIR/../.."}
# Setting up a project root was a workaround to enable support for non-standard
# structures, including monorepos. Today, CLI supports that out of the box
# and setting custom `PROJECT_ROOT` only makes it confusing.
#
# As a backwards-compatible change, I am leaving "PROJECT_ROOT" support for those
# who already use it - it is likely a non-breaking removal.
#
# For new users, we default to $PWD - not changing things all.
#
# For context: https://github.com/facebook/react-native/commit/9ccde378b6e6379df61f9d968be6346ca6be7ead#commitcomment-37914902
PROJECT_ROOT=${PROJECT_ROOT:-$PWD}

cd "$PROJECT_ROOT" || exit

Expand Down Expand Up @@ -96,6 +102,9 @@ if [[ ! -x node && -d ${HOME}/.anyenv/bin ]]; then
fi
fi

# Path to react-native folder inside node_modules
REACT_NATIVE_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"

# check and assign NODE_BINARY env
# shellcheck source=/dev/null
source "$REACT_NATIVE_DIR/scripts/node-binary.sh"
Expand Down

0 comments on commit a8e8502

Please sign in to comment.