Repository navigation
Remove Hermes vendoring once React Native ships a Hermes with Node-API #412
Description
Tracking the removal of vendor-hermes and everything that hangs off it, gated on React Native shipping a Hermes that carries Node-API.
Why we vendor today
After #372 we no longer patch Hermes — we build it from a pinned commit on the static_h branch, which carries the first-party Node-API implementation under API/napi (target hermesNapi). The pin lives in packages/host/src/node/cli/hermes.ts. On Apple platforms it is built once into an archive by the prebuilt-hermes command (packages/host/src/node/cli/hermes-prebuilt.ts) and injected into pod install through HERMES_ENGINE_TARBALL_PATH; Android (and the opt-in REACT_NATIVE_NODE_API_HERMES_FROM_SOURCE=1 path) builds it from the vendored checkout.
The host calls into it directly (hermes_napi_create_env and hermes_napi_load_module in packages/host/cpp/CxxNodeApiHostModule.cpp, with the hermes_napi_host struct and both declarations mirrored in packages/host/cpp/HermesNapiHost.hpp).
React Native's own Hermes doesn't have that code yet, which is the only reason we need REACT_NATIVE_OVERRIDE_HERMES_DIR on Android — and therefore the only reason consumers have to build React Native from source at all.
The gate
React Native doesn't tag every nightly, so read the head of the default branch rather than a release:
packages/react-native/sdks/hermes-engine/version.propertieson the default branch offacebook/react-native→HERMES_VERSION_NAME.- Check whether
facebook/hermesat taghermes-v$HERMES_VERSION_NAMEhas anAPI/napi/directory.
Last checked 2026-11-01 (not met):
HERMES_VERSION_NAME=260318099.0.2API/napi/hermes_napi.h→ 404 athermes-v260318099.0.2, whileAPI/hermes/hermes.hresolves at the same tag — so the tag is valid and carries no Node-API.- No open PR addresses this issue. Nothing to do except re-check the gate.
version=$(curl -fsSL https://raw.githubusercontent.com/facebook/react-native/main/packages/react-native/sdks/hermes-engine/version.properties | sed -n 's/^HERMES_VERSION_NAME=//p')
curl -fsSLo /dev/null "https://raw.githubusercontent.com/facebook/hermes/hermes-v$version/API/napi/hermes_napi.h" && echo "Node-API has landed in RN's Hermes ($version)"Necessary, but not sufficient
The version check tells us the source has Node-API in it; before dropping anything we still need the shipped artifacts to expose it:
- the
hermes-engineAAR'slibhermesvm.somust exporthermes_napi_create_envandhermes_napi_load_module(Hermes has to build thehermesNapitarget and keep it visible under its global-fvisibility=hidden, cf. napi: give hermes_napi.h public API C linkage meta/hermes#2106 — see the pin comment inhermes.ts), - the same for the Hermes framework shipped through the podspec on Apple platforms,
hermes_napi.h(or an equivalent public header) needs to reach us through prefab / the framework headers, soHermesNapiHost.hppcan include it instead of mirroring the struct,IHermes::getVMRuntimeUnsafe()still has to be reachable from the JSI runtime.
The real acceptance test is the test app building and passing against a stock React Native with no REACT_NATIVE_OVERRIDE_HERMES_DIR set and no build-from-source configuration.
What removal touches
packages/host/src/node/cli/hermes.tsandpackages/host/src/node/cli/hermes-prebuilt.ts— thevendor-hermesandprebuilt-hermescommands, plus their registration inpackages/host/src/node/cli/program.ts(a breaking CLI change, so it wants a major changeset)packages/host/android/build.gradle:7-17— theREACT_NATIVE_OVERRIDE_HERMES_DIRguard, andpackages/host/src/node/gradle.test.ts, which asserts that errorpackages/host/scripts/patch-hermes.rband itsrequire_relativein the podspec (including theHERMES_ENGINE_TARBALL_PATHinjection).github/workflows/check.yml— the "Clone patched Hermes version" step in the Android job (L403-408) and the prebuilt Hermes resolve/cache/build steps in the iOS job (L250-271, including the explanatory comment)apps/test-app/android/gradle.properties—react.buildFromSource=true(L47) becomes unnecessarypackages/host/cpp/HermesNapiHost.hpp— include the realhermes_napi.hinstead of mirroringhermes_napi_host, which also removes the "re-diff on every pin bump" hazarddocs/ANDROID.md,docs/CLI.md— most of the Android build-from-source guidance disappears; Android stops needing a source build (see docs: clarify the Android Hermes vendoring steps #411 for its current state)README.md(the supported-versions note),packages/host/README.md,AGENTS.md§ Critical Build Dependenciespackages/host/package.json— thereact-nativepeer dependency can widen from a single nightly (currently0.88.0-nightly-20260809-db662caea) to a real range
Related
- Provide prebuilds for Hermes patched with Node-API #177 — prebuilt Node-API Hermes, the interim mitigation if this takes a while
- macOS test app is blocked on react-native-macos ≥ 0.82 (Hermes static_h build scripts) #392 —
react-native-macosblocked on the same story - chore: better gradle setup #188 — the consumer-side Gradle settings helper, which becomes moot along with the source-build requirement
Activity
ci: fix host-cpp-tests label check to match the actual "Host 🏡" label
docs: correct the host label name to "Host 🏡"
docs: instruct Claude Code to attach CI labels when opening PRs (#436)
ci: fix host-cpp-tests label check to match the actual "Host 🏡" label
Drop the host's shadowing implementations of runtime Node-API functio…
Drop the host's shadowing implementations of runtime Node-API functio…
Drop the host's shadowing implementations of runtime Node-API functio…
Drop the host's shadowing implementations of runtime Node-API functio…
Drop the host's shadowing implementations of runtime Node-API functio…
Drop the host's shadowing implementations of runtime Node-API functio…
Drop the host's shadowing implementations of runtime Node-API functio…