The react-native-node-api package installs a react-native-node-api binary, which app and library authors use to vendor Hermes, link Node-API modules into an app and inspect how the library-naming scheme resolves for a given module.
npx react-native-node-api <command> [options]Run npx react-native-node-api help or npx react-native-node-api help <command> to see this same information from the CLI itself.
Note
This document is hand-written from the Commander program definition in packages/host/src/node/cli/program.ts (with the vendor-hermes command defined in hermes.ts and prebuilt-hermes in hermes-prebuilt.ts). It needs to be kept in sync by hand whenever a command or its options change.
Resolves an archive of the pinned Hermes, prebuilt for Apple platforms, and prints its path. This is what the Cocoapods integration uses by default: the path is handed to React Native through the HERMES_ENGINE_TARBALL_PATH environment variable, and hermes-engine.podspec then vendors the frameworks out of the archive instead of compiling Hermes as part of every app build.
The archive is looked for in this order, and cached under ~/Library/Caches/react-native-node-api/hermes-prebuilt (overridable with REACT_NATIVE_NODE_API_CACHE_PATH):
- The cache, unless
--forceis passed. - The release asset published for the pinned commit by the
Hermes prebuiltworkflow, unless--no-downloadis passed. - A local build from the vendored source, unless
--no-buildis passed. This requires macOS and Xcode, and takes a while — but only once per pinned commit.
Its name covers everything that changes its contents: the pinned Hermes commit, the React Native version whose ReactCommon/jsi it is compiled against, the build type, the platforms and the host architecture. That makes it usable as a CI cache key.
The host architecture is part of it because destroot/bin/hermesc is a native binary for whichever Mac built the archive. Archives are published from Apple Silicon runners, so an Intel Mac finds none to download and builds its own instead of getting a hermesc it cannot execute.
[from]— Path to a file inside the app package. Defaults to the current working directory.--react-native-package <package-name>— The React Native package to resolve Hermes for. Defaults toreact-native.--build-type <type>— One ofdebugorrelease.debugenables Hermes' debugger. Defaults todebug.--platform <name>— Apple platform to build for, repeatable. Defaults toiphoneosandiphonesimulator.--silent— Don't print anything except the final path. Defaults tofalse.--force— Re-resolve the archive even if it is already cached. Defaults tofalse.--no-download— Don't download a published archive.--no-build— Don't build the archive locally when none is published.--print <property>— Printname,tagorurlof the archive instead of resolving it.
To build Hermes from source as part of the app build instead — which is the faster loop while iterating on Hermes itself, since Xcode then rebuilds it incrementally — set REACT_NATIVE_NODE_API_HERMES_FROM_SOURCE=1 before running pod install. Setting REACT_NATIVE_OVERRIDE_HERMES_DIR or HERMES_ENGINE_TARBALL_PATH yourself also takes precedence.
Clones the pinned commit of Hermes' static_h branch (which carries Hermes' first-party Node-API implementation) into the sdks/node-api-hermes directory of the app's react-native package, so the native build can compile against it. Prints the path to the vendored checkout on success.
This is how Hermes is built on Android, and on Apple when the from-source path described above is selected.
[from]— Path to a file inside the app package. Defaults to the current working directory.--react-native-package <package-name>— The React Native package to vendor Hermes into. Defaults toreact-native.--silent— Don't print anything except the final path. Defaults tofalse.--force— Don't check timestamps of input files to skip unnecessary rebuilds; removes and re-clones an existing checkout. Defaults tofalse.
Auto-links the Node-API modules found among the app's dependencies for one or more platforms, copying (and, on Apple, signing) them into place.
[path]— Some path inside the app package. Defaults to the current working directory.--android— Link Android modules.--apple— Link Apple modules.--prune— Delete previously vendored modules that are no longer auto-linked. Defaults totrue.--package-name <strategy>— Controls how a dependency's package name is transformed into a library name. One ofstrip,keeporomit(see Library naming below). Defaults tostrip, or theNODE_API_PACKAGE_NAMEenvironment variable if set.--path-suffix <strategy>— Controls how the path of the addon inside a package is transformed into a library name. One ofstrip,keeporomit(see Library naming below). Defaults tostrip, or theNODE_API_PATH_SUFFIXenvironment variable if set.
At least one of --android / --apple must be passed, or the command exits with an error listing the supported platforms.
Lists the Node-API modules found among the dependencies of the package at (or above) a path, without linking them.
[from-path]— Some path inside the app package. Defaults to the current working directory.--json— Output the result as JSON instead of a human-readable summary. Defaults tofalse.--package-name <strategy>— Same as forlink(see Library naming).--path-suffix <strategy>— Same as forlink(see Library naming).
Utility to print the resolved module path, package name and computed library name for a single Node-API module, given its path. Useful for debugging naming collisions.
<path>— Path to a Node-API module (e.g. an*.android.nodedirectory or*.apple.nodeframework).--package-name <strategy>— Same as forlink(see Library naming).--path-suffix <strategy>— Same as forlink(see Library naming).
Patches the app's Xcode project to add a build phase which copies, renames and signs the Node-API frameworks (equivalent to running link --apple as part of the Xcode build). Only supported on macOS.
[path]— Some path inside the app package. Defaults to the current working directory.
--package-name and --path-suffix both control how the cross-platform library name (package-name--path-component--addon-name) is derived, and accept the same three strategies. Given a package @my-org/my-pkg with an addon at build/Release/my-addon.node:
| Strategy | --package-name effect |
--path-suffix effect |
|---|---|---|
strip |
Scope is dropped: my-pkg--my-addon |
Path is reduced to its basename: my-pkg--my-addon |
keep |
Scope is kept: my-org--my-pkg--my-addon |
Full path is kept: my-pkg--build-Release-my-addon |
omit |
Package name is dropped: my-addon |
Path is dropped: my-pkg |