Hermes — その概要、React Native向けJSエンジンと動作原理

著者: IT Sectr 公開日: 2026-07-06 読了時間: 9 分

HermesはAOT(Ahead-of-Time)コンパイルを備えたJavaScriptエンジンで、MetaによってReact Native向けに開発され、メモリが限られたモバイルデバイス向けに最適化されています。Meta Engineeringの公式ブログ(2022年)によると、HermesはJavaScriptCoreと比較してアプリの起動時間を20〜50%短縮し、バンドルサイズを30〜40%削減します。V8やJSCとは異なり、Hermesはデバイス上でJITコンパイルを使用しません。すべてのJavaScriptはHermes CLIを介してビルド時にバイトコードにコンパイルされます。これは、JITコンパイルがApp Storeのポリシーで制限されているiOSで特に重要です。

重要なポイント

  • Hermes — AOTコンパイルを備えたJavaScriptエンジン、MetaがReact Native向けに開発
  • AOT vs JIT — Hermesはビルド時にJSをバイトコードにコンパイル、デバイス上でJIT不要
  • パフォーマンス — アプリ起動が20〜50%高速化、バンドルが30〜40%小型化
  • Hades GC — モバイルシナリオ向けに最適化された低レイテンシのガベージコレクタ
  • 標準 — ECMAScript 2020+(Proxy、BigInt、Reflectの完全サポートなし)

Hermesとは

Hermesは、MetaによってReact Native向けに作られたコンパクトなオープンソース(MITライセンス)のJavaScriptエンジンで、リソースが限られたモバイルデバイス上で動作するように最適化されています。Hermesの主な革新は、JITコンパイルを廃止し、AOT(Ahead-of-Time)を採用したことです。React Nativeアプリのビルドフェーズで、Metro BundlerがコンパイルされたJavaScriptをHermes CLIに渡し、それがHBC(Hermes ByteCode)バイトコードに変換します。このバイトコードは、デバイス上での追加コンパイルなしにエンジンによって直接実行されます。このアプローチにより、予測可能なパフォーマンスが得られます。JITのウォームアップも、コンパイルの一時停止も、余分なバッテリー消費もありません。Hermesはモバイルデバイスの制限を考慮して設計されています。少ないRAM(1〜4 GB)、限られた消費電力、高速なコールドスタートの必要性です。Hermesの最初のパブリックリリースは2019年で、React Native 0.70(2022年)以降、このエンジンはAndroidの標準になりました。

Hermes vs JavaScriptCore:エンジン比較

JavaScriptCore(JSC)は、SafariとReact Native(バージョン0.70以前)が使用する標準のWebKitエンジンです。JSCはJITコンパイルをサポートしており、複雑なJavaScript操作で高いパフォーマンスを提供します。ただし、JITにはウォームアップが必要です。実行の最初の数秒は遅く(インタプリタモード)、その後JITがホットパスをコンパイルします。iOSでは、App Storeのポリシー(動的コード生成の禁止)によりJITは実質的に利用できないため、iOS上のJSCはインタプリタモードでのみ動作し、パフォーマンスが低下します。JSCはバイナリサイズが大きく(約10 MB)、JITインフラストラクチャのためにより多くのRAMを消費します。HermesはJITに依存せず、起動(コールドスタート)後すぐに予測可能なパフォーマンスを提供します。JSCはECMAScript標準をより完全にサポートしています(Proxy、BigInt、Reflectを含む)が、より多くのリソース消費を代償とします。コールドスタートと小さなサイズが重要なReact Nativeプロジェクトでは、Hermesが適しています。負荷の高いJS計算(ゲーム、WebGL)を伴うプロジェクトでは、JSCの方が高いピークパフォーマンスを発揮する可能性があります。

パラメータHermesJavaScriptCore
コンパイルAOT(ビルド時)JIT + インタプリタ(デバイス上)
コールドスタート20〜50%高速ベースライン
バンドルサイズ30〜40%小さいベースライン
RAM使用量20〜30%少ないベースライン
ECMAScriptES2020(制限あり)ES2022+(完全)
iOS JIT不要利用不可(インタプリタのみ)
バイナリ約3 MB約10 MB

AOTコンパイル:事前ビルドの仕組み

AOTコンパイル(Ahead-of-Time)はHermesで2段階で行われます。最初の段階では、Metro BundlerがJavaScriptファイルを1つのバンドルにまとめ、Hermes CLI(ユーティリティhermesc)に渡します。2番目の段階では、hermescがJavaScript ASTを解析し、中間表現HIR(Hermes Intermediate Representation)を生成して、バイナリHBCバイトコードを出力します。結果は、元のJavaScriptを含まずバイトコードのみを含む.hbcファイルです。Hermesランタイムは、解析やコンパイルなしでHBCを直接ロードします。これにより、起動が劇的に高速化されます。数千行のJSを解析する(非同期)代わりに、エンジンは事前コンパイルされたバイナリ形式を読み取ります。AOTはサイズも削減します。バイトコードはJavaScript ASTよりも平均30%コンパクトです。AOTの欠点は、実行時にeval、new Function、または動的requireを実行できないことです。すべてのモジュールはビルド時に認識されている必要があります。

bash
# Hermes CLIをスタンドアロンでインストール
npm install hermes-engine

# JSをHBCバイトコードにコンパイル
npx hermesc -emit-binary -out bundle.hbc bundle.js

# バイトコード統計
npx hermesc -dump-bytecode bundle.hbc  # shows HBC instructions

# 元のJSとHBCサイズの比較
wc -c bundle.js      # 2,300,000 bytes
wc -c bundle.hbc     # 1,450,000 bytes (37% reduction)

Hermesのパフォーマンス指標

Hermesのパフォーマンスは、TTI(Time-To-Interactive)、APK/IPAサイズ、RAM消費量の3つの主要指標で測定されます。Metaのデータによると、AndroidではHermesはJSCと比較してTTIを34%削減します。ミッドレンジデバイス(Moto G7)で4.2秒から2.8秒になります。コンパクトなバイトコードとJITライブラリがないため、APKサイズは28%減少します。同じ負荷でのRAM消費量は平均22%低下します。これは特に2〜3 GBのRAMを搭載したデバイスで重要です。iOSでは、JSCがJITを使用できないため、その効果はさらに顕著で、HermesはTTIを最大45%改善します。指標はMetaがFacebook Liteアプリで行ったテストに基づいています。実際のプロジェクトでは、効果は異なります。シンプルな画面(リスト、テキスト)ではHermesの改善効果が大きく、負荷の高いアニメーションでは小さくなります。プロファイリングツール:React Native Profiler + hermes profile --heap

Hermesでのメモリプロファイリング

Hermesには、Chrome DevToolsからアクセス可能な組み込みメモリプロファイラが含まれています。Metroを介してアプリに接続し、[メモリ]タブを開いて、スナップショットタイプからHermes(JavaScript)を選択します。Hermesは3種類のスナップショットをサポートしています。Heap Snapshot(すべてのオブジェクト)、Allocation Timeline(オブジェクトのライフタイム)、Allocation Sampling(サンプリングプロファイル)です。Hades GCはGCの一時停止を最小限に抑えます。10秒の動作あたり平均1回の2〜5msの一時停止で、同じ期間のJSCの10〜20msの一時停止と比較されます。

Hades GCガベージコレクタ

Hades GCはHermesのガベージコレクタで、最小限の一時停止でモバイルシナリオ向けに設計されています。JSCのmark-sweep GCとは異なり、Hadesはコンカレントコレクションを使用します。コレクタはメインの実行スレッドと並行して動作し、短い間隔でのみ停止します。Hades GCはヒープを世代に分割します。若い世代(nursery)は頻繁かつ迅速に収集され(Scavenge)、古い世代はより少ない頻度で、より短い一時停止で収集されます。ヒープサイズは設定可能で、デフォルトはアプリの利用可能RAMの2/3、最小しきい値は32 MBです。Hadesはstop-the-worldアプローチを使用しません。古い世代の完全なコレクションでも5〜8msを超えません。コレクタは典型的なモバイルシナリオ向けに最適化されています。多くの短命オブジェクト(一時的な文字列、Reactファイバーオブジェクト)と、少数の長命オブジェクトです。オブジェクトの生成が多いアプリケーション(リスト、アニメーション)では、HadesはJSCと比較してよりスムーズなFPSを提供します。

React NativeプロジェクトでHermesを有効にする方法

Hermesの有効化は、React Nativeのバージョンとプラットフォームによって異なります。React Native 0.70以降、新しいプロジェクトではAndroidでHermesがデフォルトで有効になっています。iOSでは、Hermesはオプションです。Androidで有効にするには、ファイルandroid/app/build.gradleproject.ext.react.enableHermesブロックでenableHermes: trueを設定します。iOSの場合:use_react_native!(:path => config[:reactNativePath], :hermes_enabled => true)を使用してPodfileでhermes_enabledtrueに設定します。有効にしたら、pod installを実行します。既存のプロジェクトでは、ライブラリの互換性を確認してください。HermesはProxy、eval、および一部のES2021機能をサポートしていません。設定を確認するには、npx react-native infoを使用します。HermesとJSCを切り替えるには、フラグを変更してクリーンリビルドを実行します。

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

// iOS/Podfile — iOSでHermesを有効化
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の制限:サポートされていない機能

Hermesの主な制限は、JITがないことに関連しています。Hermesは以下をサポートしていません。ProxyおよびReflect API(MobX、Vue、一部の状態管理で使用)、BigInt(大きな数値)、Symbol.toStringTagWeakRefおよびFinalizationRegistry。eval関数とnew Function関数は実行時に例外をスローします。this引数を持つArray.prototype.flatおよびflatMapメソッドのコールバックは制限付きで動作します。タイムゾーンを含むISO 8601の日付形式は完全には処理されません。これらの制限のほとんどは、典型的なReact Nativeアプリケーションには影響しません。ReactとReact Nativeは限られたES機能セットを使用します。ライブラリがProxyを必要とする場合(例:Proxyを使用するMobX 6+)、configure({ useProxies: false })を使用するか、代替手段を選択してください。既存のコードの互換性を確認するには、バンドルに対してnpx hermesc -checkを実行します。サポートされていない機能のリストが表示されます。

  • Proxy / Reflect — 未実装。Proxyを必要とするライブラリはフォールバックモードが必要
  • BigInt — 利用不可。大きな数値にはbignumber.jsライブラリを使用
  • eval / new Function — 呼び出すと例外。すべてのモジュールは静的である必要がある
  • WeakRef / FinalizationRegistry — 未サポート。代替手段なし
  • Symbol.toStringTag — 無視される。instanceofは正しく動作

よくある質問

アプリがHermesで動作しているか確認する方法

アプリコンソールでconsole.log(global.HermesInternal)を実行します。HermesInternalオブジェクトが存在する場合、アプリはHermesで動作しています。代替方法:console.log(global.HermesInternal?.getRuntimeProperties()) — エンジンのバージョンとGCパラメータが出力されます。Releaseビルドでは、サイズを最小化するためにHermesInternalが利用できない場合があります。

Hermesを有効にした後、iOSでアプリがクラッシュするのはなぜですか?

Podfileの設定を確認してください。iOSのHermesはNew Architecture(Fabric Renderer)を必要とします。:hermes_enabled => trueを設定し、pod install --repo-updateを実行します。プロジェクトがReact Native 0.70未満からアップグレードする場合は、New Architectureとのライブラリ互換性を確認してください。サードパーティのライブラリがJSCを必要とする場合は、Hermesを無効にします。フラグをfalseに変更し、Podsを再インストールします。

Hermesは開発中のHot Reloadに影響しますか?

いいえ、HermesはHot Reload / Fast Refreshに影響しません。開発中、MetroはHermesコンパイルなしでJavaScriptバンドルを実行します(プレーンJS)。HermesバイトコードはReleaseビルドでのみコンパイルされます。Debugモードでは、標準のJavaScriptCoreまたはインタプリタモードのHermesが使用されます。設定でHermesが有効になっていても、Hot Reloadの速度は変わりません。切り替えはプロダクションビルド段階でのみ行われます。

HermesはExpoで使用できますか?

はい、Expo SDK 45以降、Hermesはmanagedワークフローでサポートされています。app.jsonで"jsEngine": "hermes"を指定します。bareワークフローの場合、Hermesは通常のReact Nativeプロジェクトと同様に動作します。Expo GoはHermesをサポートしていません。Hermesを使用したビルドには、Expo Dev ClientまたはEAS Buildを使用してください。expo doctorでライブラリの互換性を確認してください。

自分のプロジェクトでHermesとJSCのパフォーマンスを比較する方法

React Native Performance Monitor(FPS指標)とHermes Profiling Toolsを使用します。同じデバイス上でHermes版とJSC版の2つのアプリバージョンを作成します。コールドスタート(アイコンをタップしてから最初のインタラクティブ画面まで)、TTI(Time-To-Interactive)、APK/IPAサイズ、最大RAM消費量を測定します。各構成で少なくとも3回テストを実行します。典型的なHermesの利点:起動が20〜40%高速、RAMが15〜25%少ない。

まとめ

  • Hermes — React Native向けAOTコンパイルを備えたMetaのJavaScriptエンジン、Android 0.70以降標準
  • AOTコンパイルにより、デバイス上でのJITウォームアップなしで予測可能なパフォーマンスを実現
  • コールドスタートが20〜50%高速、バンドルサイズがJavaScriptCore比30〜40%小型
  • Hades GC — JSCの10〜20msに対して2〜5msの一時停止のコンカレントガベージコレクタ
  • 制限:Proxy、BigInt、eval、WeakRefは未サポート。ライブラリを確認
  • 有効化:build.gradleのenableHermes(Android)またはPodfileのhermes_enabled(iOS)
  • Hermes CLIで.hbcバイトコードのコンパイルとDevToolsによるメモリプロファイリングが可能
  • Hermesは開発中のHot Reloadに影響せず、バイトコードはReleaseのみでコンパイル

ターンキー方式のモバイルアプリケーションを開発します

IT Sectrは2017年からスタートアップや企業向けにiOS・Androidアプリケーションを開発しています。私たちがご相談に乗り、最適なソリューションをご提案します。

プロジェクトについて相談

こちらもお読みください