Hermes — what it is, JS engine for React Native and how it works

Author: IT Sectr Published: 2026-07-06 Reading time: 9 min

Hermes is a JavaScript engine with AOT (Ahead-of-Time) compilation, developed by Meta for React Native and optimized for mobile devices with limited memory. According to the official Meta Engineering blog (2022), Hermes reduces app startup time by 20-50% and decreases bundle size by 30-40% compared to JavaScriptCore. Unlike V8 or JSC, Hermes does not use JIT compilation on the device — all JavaScript is compiled into bytecode at build time via the Hermes CLI. This is especially important for iOS, where JIT compilation is restricted by App Store policies.

Key Takeaways

  • Hermes — a JavaScript engine with AOT compilation, developed by Meta for React Native
  • AOT vs JIT — Hermes compiles JS to bytecode at build time, without JIT on the device
  • Performance — app startup 20-50% faster, bundle 30-40% smaller
  • Hades GC — low-latency garbage collector optimized for mobile scenarios
  • Standard — ECMAScript 2020+ without full Proxy, BigInt and Reflect support

What Is Hermes

Hermes is a compact open-source JavaScript engine (MIT license) created by Meta for React Native and optimized to run on resource-constrained mobile devices. The main innovation of Hermes is abandoning JIT compilation in favor of AOT (Ahead-of-Time). During the React Native app build phase, Metro Bundler passes the compiled JavaScript to Hermes CLI, which transforms it into HBC (Hermes ByteCode) bytecode. This bytecode is executed directly by the engine without additional compilation on the device. This approach provides predictable performance: no JIT warming up, no compilation pauses, no extra battery drain. Hermes is designed with mobile device limitations in mind: small RAM (1-4 GB), limited power consumption, and the need for fast cold starts. The first public release of Hermes was in 2019, and starting with React Native 0.70 (2022), the engine became the standard on Android.

Hermes vs JavaScriptCore: Engine Comparison

JavaScriptCore (JSC) is the standard WebKit engine used by Safari and React Native prior to version 0.70. JSC supports JIT compilation, which provides high performance for complex JavaScript operations. However, JIT requires warm-up: the first seconds of execution are slower (interpreted mode), then JIT compiles hot paths. On iOS, JIT is practically unavailable due to App Store policies (ban on dynamic code generation), so JSC on iOS works only in interpreted mode — performance drops. JSC has a larger binary size (about 10 MB) and consumes more RAM due to JIT infrastructure. Hermes does not depend on JIT, providing predictable performance immediately after startup (cold start). JSC supports the ECMAScript standard more fully (including Proxy, BigInt, Reflect), but at the cost of higher resource consumption. For React Native projects where cold start and small size are critical — Hermes is preferable. For projects with heavy JS computations (games, WebGL) — JSC may deliver higher peak performance.

ParameterHermesJavaScriptCore
CompilationAOT (at build time)JIT + Interpreted (on device)
Cold start20-50% fasterBaseline
Bundle size30-40% smallerBaseline
RAM usage20-30% lessBaseline
ECMAScriptES2020 (limitations)ES2022+ (full)
iOS JITNot requiredUnavailable (interpreted only)
Binary~3 MB~10 MB

AOT Compilation: How Ahead-of-Time Build Works

AOT compilation (Ahead-of-Time) in Hermes happens in two stages. In the first stage, Metro Bundler collects JavaScript files into a single bundle and passes it to Hermes CLI (the hermesc utility). In the second stage, hermesc parses the JavaScript AST, generates an intermediate representation HIR (Hermes Intermediate Representation), and then emits binary HBC bytecode. The result is a .hbc file that contains only bytecode without the original JavaScript. The Hermes runtime loads HBC directly, without parsing and compilation. This radically speeds up startup: instead of parsing thousands of lines of JS (async), the engine reads a precompiled binary format. AOT also reduces size: bytecode is on average 30% more compact than JavaScript AST. The downside of AOT — inability to execute eval, new Function or dynamic require at runtime — all modules must be known at build time.

bash
# Install Hermes CLI standalone
npm install hermes-engine

# Compile JS to HBC bytecode
npx hermesc -emit-binary -out bundle.hbc bundle.js

# Bytecode statistics
npx hermesc -dump-bytecode bundle.hbc  # shows HBC instructions

# Original JS vs HBC size
wc -c bundle.js      # 2,300,000 bytes
wc -c bundle.hbc     # 1,450,000 bytes (37% reduction)

Hermes Performance Metrics

The performance of Hermes is measured by three key metrics: Time-To-Interactive (TTI), APK/IPA size, and RAM consumption. According to Meta data, on Android Hermes reduces TTI by 34% compared to JSC: from 4.2 seconds to 2.8 seconds on a mid-range device (Moto G7). APK size decreases by 28% thanks to compact bytecode and the absence of JIT libraries. RAM consumption is on average 22% lower under the same load — this is especially important for devices with 2-3 GB of RAM. On iOS, the gain is even more significant: since JSC cannot use JIT, Hermes provides up to 45% TTI improvement. Metrics are based on Meta's tests with the Facebook Lite app. In real projects, the gain varies: for simple screens (lists, text) Hermes gives a larger improvement, for heavy animations — a smaller one. Profiling tool: React Native Profiler + hermes profile --heap.

Memory Profiling with Hermes

Hermes includes a built-in memory profiler accessible via Chrome DevTools. Connect to the app through Metro, open the Memory tab and select Hermes (JavaScript) from snapshot types. Hermes supports three snapshot types: Heap Snapshot (all objects), Allocation Timeline (object lifetimes) and Allocation Sampling (sampling profile). Hades GC reduces GC pauses to a minimum — on average one 2-5ms pause per 10 seconds of operation, compared to 10-20ms pauses for JSC over the same period.

Hades GC Garbage Collector

Hades GC is the garbage collector in Hermes, designed for mobile scenarios with minimal pauses. Unlike the mark-sweep GC in JSC, Hades uses concurrent collection: the collector works in parallel with the main execution thread, stopping it only for short intervals. Hades GC divides the heap into generations: the young generation (nursery) is collected frequently and quickly (Scavenge), the old generation is collected less often with smaller pauses. The heap size is configurable: by default — 2/3 of the app's available RAM, minimum threshold — 32 MB. Hades does not use a stop-the-world approach: even a full old generation collection takes no more than 5-8ms. The collector is optimized for typical mobile scenarios: many short-lived objects (temporary strings, React fiber objects), few long-lived ones. For applications with intensive object creation (lists, animations), Hades provides smoother FPS compared to JSC.

How to Enable Hermes in a React Native Project

Enabling Hermes depends on the React Native version and platform. Starting with React Native 0.70, Hermes is enabled by default for Android in new projects. For iOS, Hermes is optional. To enable on Android: in the file android/app/build.gradle set enableHermes: true in the project.ext.react.enableHermes block. For iOS: set hermes_enabled to true in the Podfile via use_react_native!(:path => config[:reactNativePath], :hermes_enabled => true). After enabling, run pod install. For existing projects, check library compatibility: Hermes does not support Proxy, eval, and some ES2021 features. Use npx react-native info to verify configuration. To switch between Hermes and JSC, change the flag and perform a clean rebuild.

groovy
// android/app/build.gradle — enable Hermes
project.ext.react = [
    enableHermes: true,
    cliPath: "node_modules/react-native/cli.js"
]

// iOS/Podfile — enable Hermes on iOS
require_relative '../node_modules/react-native/scripts/react_native_pods'
require_relative '../node_modules/@react-native-community/cli-platform-ios/native_modules'

target 'MyApp' do
  config = use_native_modules!
  use_react_native!(
    :path => config[:reactNativePath],
    :hermes_enabled => true
  )
end

Hermes Limitations: What Is Not Supported

The main limitations of Hermes are related to the lack of JIT. Hermes does not support: Proxy and Reflect API (used in MobX, Vue, some state managers), BigInt (large numbers), Symbol.toStringTag, WeakRef and FinalizationRegistry. The eval and new Function functions throw an exception at runtime. Callbacks of Array.prototype.flat and flatMap with a this argument work with limitations. ISO 8601 date formats with timezones are not fully processed. Most of these limitations do not affect typical React Native applications: React and React Native use a limited set of ES features. If a library requires Proxy (for example, MobX 6+ with Proxy), use configure({ useProxies: false }) or choose an alternative. To check compatibility of existing code, run npx hermesc -check on your bundle — it will show the list of unsupported features.

  • Proxy / Reflect — not implemented; libraries requiring Proxy need fallback mode
  • BigInt — unavailable; use bignumber.js libraries for large numbers
  • eval / new Function — throws on call; all modules must be static
  • WeakRef / FinalizationRegistry — not supported; no alternative
  • Symbol.toStringTag — ignored; instanceof works correctly

Frequently Asked Questions

How to check if the app is running on Hermes?

In the app console, run console.log(global.HermesInternal). If the HermesInternal object exists — the app is running on Hermes. Alternatively: console.log(global.HermesInternal?.getRuntimeProperties()) — will output the engine version and GC parameters. In Release builds, HermesInternal may be unavailable to minimize size.

Why does the app crash on iOS after enabling Hermes?

Check your Podfile settings: Hermes on iOS requires New Architecture (Fabric Renderer). Set :hermes_enabled => true, run pod install --repo-update. If the project is upgrading from React Native below 0.70, check library compatibility with New Architecture. Disable Hermes if a third-party library requires JSC — change the flag to false and reinstall Pods.

Does Hermes affect Hot Reload during development?

No, Hermes does not affect Hot Reload / Fast Refresh. During development, Metro runs the JavaScript bundle without Hermes compilation (plain JS). Hermes bytecode is built only for Release builds. In Debug mode, standard JavaScriptCore or Hermes in interpreted mode is used. Hot Reload speed does not change when Hermes is enabled in configuration — switching occurs only at the production build stage.

Can Hermes be used with Expo?

Yes, starting from Expo SDK 45, Hermes is supported for managed workflow. In app.json set "jsEngine": "hermes". For bare workflow, Hermes works as in a regular React Native project. Expo Go does not support Hermes — use Expo Dev Client or EAS Build for builds with Hermes. Check library compatibility via expo doctor.

How to compare Hermes and JSC performance in my project?

Use React Native Performance Monitor (FPS metrics) and Hermes Profiling Tools. Build two versions of the app — with Hermes and JSC — on the same device. Measure: cold start (from tapping the icon to the first interactive screen), TTI (Time-To-Interactive), APK/IPA size, and peak RAM consumption. Run tests at least 3 times for each configuration. Typical Hermes advantage: 20-40% faster startup, 15-25% less RAM.

Summary

  • Hermes — a Meta JavaScript engine with AOT compilation for React Native, standard on Android since 0.70
  • AOT compilation provides predictable performance without JIT warm-up on the device
  • Cold start 20-50% faster, bundle size 30-40% smaller vs JavaScriptCore
  • Hades GC — concurrent garbage collector with 2-5ms pauses instead of 10-20ms for JSC
  • Limitations: Proxy, BigInt, eval, WeakRef not supported — check your libraries
  • Enabling: enableHermes in build.gradle (Android) or hermes_enabled in Podfile (iOS)
  • Hermes CLI allows compiling .hbc bytecode and profiling memory via DevTools
  • Hermes does not affect Hot Reload in development — bytecode is built only for Release

We will develop a mobile application turnkey

IT Sectr creates iOS and Android applications for startups and businesses since 2017. We will advise you and propose the best solution.

Discuss the project

Read also