Skip to content
useffect.sh
Book 30 min with a senior
Performance

Hermes

Meta’s JavaScript engine for React Native, the default since 0.70, which precompiles the bundle to bytecode at build time.

Definition

Hermes is the open-source JavaScript engine Meta built specifically for React Native. It has been the default engine since React Native 0.70, replacing JavaScriptCore, the Safari engine React Native used originally. Its defining trait: in release builds, the JavaScript bundle is compiled to Hermes bytecode (a .hbc file) at build time, not on the phone. The engine no longer has to parse and compile JavaScript at launch, which cuts startup time, memory use, and app size. Every React Native release ships with the matching Hermes version. Since React Native 0.84, Hermes V1, a new generation of the compiler and VM, is the default engine on both iOS and Android, after an experimental opt-in phase in 0.82. React Native DevTools only works with it: an app switched back to JavaScriptCore loses the built-in debugger, breakpoints and profiling included.

In a real app

To check which engine is running, !!global.HermesInternal in the console is enough, and HermesInternal.getRuntimeProperties() gives the exact version. The pitfall the React Native team documents: if the bundle is loaded in a non-standard way (a bundle downloaded by a home-grown update system, say), HermesInternal can be present while the app is loading plain JavaScript instead of .hbc bytecode. The startup gain vanishes with no error message. With EAS Update, the published bundle is compiled to bytecode for the build’s Hermes version.

Hermes is only worth measuring in release. A debug build keeps sources and debugging hooks, and any startup number taken on it is wrong. npx expo run:ios --configuration Release or yarn android --mode release give the real figure. On the language side, Hermes implements ECMAScript at its own pace; an Intl polyfill or a recent API can be missing, which is why date and number formatting should be tested on device rather than in Node.

For Hermes V1, the switch is automatic from 0.84 (Expo SDK 56 and later). Going back to the previous Hermes means pinning hermes-compiler to 0.15.0 in package.json (overrides or resolutions), setting hermesV1Enabled=false on Android and RCT_HERMES_V1_ENABLED=0 at pod install, which forces React Native to build from source. You need a specific reason to do that.

Our services on this

Sources

All 35 glossary terms

One of these is blocking your app?

30 minutes with a senior to look at the problem in your code. Free.