Skip to content
Open
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .changeset/salty-mugs-judge.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
'@react-native-node-api/test-app': patch
'react-native-node-api': patch
---

Improvements to setup scripts, updated docs
1 change: 1 addition & 0 deletions .nvmrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
22
4 changes: 4 additions & 0 deletions apps/test-app/android/settings.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,7 @@ apply(from: {
throw new GradleException("Could not find `react-native-test-app`");
}())
applyTestAppSettings(settings)

// customize the path to match your node_modules location
apply(from: "../../../node_modules/react-native-node-api/android/consumerSettings.gradle")
Copy link
Collaborator

@kraenhansen kraenhansen Jul 17, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder now ... how this ever worked 🤔

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right, that's already set up thanks to RNTA's scripts - I wasn't aware that you had it configured from my talk to @paradowstack before I jumped into the scripts. Do you think we should leave it there / maybe commented, as a reference sample, additionally to the MD docs? I think some may be concerned that the sample app does not contain this configuration if they browse its source for reference.

applyNodeAPISettings(settings)
27 changes: 25 additions & 2 deletions docs/ANDROID.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,36 @@
# Android support

## Building Hermes from source
## Android setup

### Step 1: `settings.gradle`

Gradle needs special handling to build React Native from source. In your app's `settings.gradle` please include the below:

```groovy
// customize the path to match your node_modules location
apply(from: "../../../node_modules/react-native-node-api/android/consumerSettings.gradle")
applyNodeAPISettings(settings)
```

### Step 2: script for adjusting environment variables

To integrate automatic setup of Hermes engine, a special env variable (`REACT_NATIVE_OVERRIDE_HERMES_DIR`) must be set to a proper path. Since Gradle does not really support loading `.env` files, this must be automated by the consumer. We provide the script `react-native-node-api vendor-hermes --silent` which will output a single line, the path to Hermes directory.

Each time you run Android Studio, make sure this is in place.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Each time you run Android Studio, make sure this is in place.
Each time you run Android Studio or start the Android app from a terminal, make sure this is in place.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd only change 'start' to 'build' - applied 👍


### How it works: building Hermes from source

Because we're using a version of Hermes patched with Node-API support, we need to build React Native from source.

Alternatively, if for whatever reason you want to do it manually, you can do so by exporting this environment variable before Gradle invocation:

```
export REACT_NATIVE_OVERRIDE_HERMES_DIR=`npx react-native-node-api vendor-hermes --silent`
export REACT_NATIVE_OVERRIDE_HERMES_DIR="$(npx react-native-node-api vendor-hermes --silent)"
```

> [!TIP]
> This above automatically done by our script. If you run it from postinstall, there is no need to do this manually.
## Cleaning your React Native build folders

If you've accidentally built your app without Hermes patched, you can clean things up by deleting the `ReactAndroid` build folder.
Expand Down
7 changes: 7 additions & 0 deletions docs/IOS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# iOS support

## iOS setup: script for adjusting environment variables

To integrate automatic setup of Hermes engine, a special env variable (`REACT_NATIVE_OVERRIDE_HERMES_DIR`) must be set to a proper path. We provide the script `react-native-node-api vendor-hermes --silent` which will output a single line, the path to Hermes directory.

Each time you run XCode, make sure this is in place.
2 changes: 2 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@
"test": "npm run test --workspace react-native-node-api --workspace cmake-rn --workspace gyp-to-cmake --workspace node-addon-examples",
"bootstrap": "npm run build && npm run bootstrap --workspaces --if-present",
"prerelease": "npm run build && npm run prerelease --workspaces --if-present",
"release": "changeset publish"
"release": "changeset publish",
"postinstall": "npm run build"
},
"author": {
"name": "Callstack",
Expand Down
22 changes: 22 additions & 0 deletions packages/host/android/consumerSettings.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import org.gradle.initialization.DefaultSettings


ext.applyNodeAPISettings = { DefaultSettings settings ->
def searchDirectory = rootDir.toPath()
do {
def p = searchDirectory.resolve("node_modules/react-native")
if (p.toFile().exists()) {
println "[RN-NAPI] Found React Native in ${p.toRealPath().toString()}"

includeBuild(p.toRealPath().toString()) {
dependencySubstitution {
substitute(module("com.facebook.react:react-android")).using(project(":packages:react-native:ReactAndroid"))
substitute(module("com.facebook.react:react-native")).using(project(":packages:react-native:ReactAndroid"))
substitute(module("com.facebook.react:hermes-android")).using(project(":packages:react-native:ReactAndroid:hermes-engine"))
substitute(module("com.facebook.react:hermes-engine")).using(project(":packages:react-native:ReactAndroid:hermes-engine"))
}
}
break
}
} while (searchDirectory = searchDirectory.getParent())
}
6 changes: 3 additions & 3 deletions packages/host/src/node/cli/hermes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ export const command = new Command("vendor-hermes")
successText: "Removed existing Hermes clone",
failText: (error) =>
`Failed to remove existing Hermes clone: ${error.message}`,
isEnabled: !silent,
isSilent: silent,
}
);
}
Expand Down Expand Up @@ -84,7 +84,7 @@ export const command = new Command("vendor-hermes")
successText: "Cloned custom Hermes",
failText: (err) =>
`Failed to clone custom Hermes: ${err.message}`,
isEnabled: !silent,
isSilent: silent,
}
);
} catch (error) {
Expand Down Expand Up @@ -117,7 +117,7 @@ export const command = new Command("vendor-hermes")
successText: "Copied JSI from patched Hermes to React Native",
failText: (err) =>
`Failed to copy JSI from Hermes to React Native: ${err.message}`,
isEnabled: !silent,
isSilent: silent,
}
);
console.log(hermesPath);
Expand Down
Loading