Hermes — 是什么,React Native的JS引擎及工作原理

作者: IT Sectr 发布日期: 2026-07-06 阅读时间: 9 分钟

Hermes — 是一个带有AOT(Ahead-of-Time)编译的JavaScript引擎,由Meta为React Native开发,并针对内存有限的移动设备进行了优化。根据Meta Engineering官方博客(2022),与JavaScriptCore相比,Hermes将应用程序启动时间减少了20-50%,并将捆绑包大小减少了30-40%。与V8或JSC不同,Hermes不在设备上使用JIT编译 — 所有JavaScript在构建阶段通过Hermes CLI编译成字节码。这对于iOS尤其重要,因为JIT编译受到App Store策略的限制。

要点

  • 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 — 是一个紧凑的开源(MIT许可证)JavaScript引擎,由Meta为React Native创建,并针对在资源有限的移动设备上运行进行了优化。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与JavaScriptCore:引擎对比

JavaScriptCore(JSC)— 标准的WebKit引擎,由Safari和0.70版本之前的React Native使用。JSC支持JIT编译,为复杂的JavaScript操作提供了高性能。但JIT需要预热:前几秒代码运行较慢(解释模式),然后JIT编译热点部分。在iOS上,由于App Store策略(禁止动态代码生成),JIT实际上不可用,因此JSC在iOS上仅以解释模式运行 — 性能下降。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中分两个阶段进行。在第一阶段,Metro Bundler将JavaScript文件收集到单个捆绑包中,并将其传递给Hermes CLI(hermesc工具)。在第二阶段,hermesc解析JavaScript AST,生成中间表示HIR(Hermes Intermediate Representation),然后发出二进制HBC字节码。结果是一个扩展名为.hbc的文件,仅包含字节码而不包含原始JavaScript。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的性能通过三个关键指标来衡量:Time-To-Interactive(TTI)、APK/IPA大小和RAM消耗。据Meta称,在Android上,与JSC相比,Hermes将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连接到应用程序,打开Memory选项卡,在快照类型中选择Hermes(JavaScript)。Hermes支持三种快照类型:Heap Snapshot(所有对象)、Allocation Timeline(对象生命周期)和Allocation Sampling(选择性分析)。Hades GC将GC暂停次数降至最低 — 平均每10秒工作一次2-5ms的暂停,而JSC在同一时期有10-20ms的暂停。

Hades GC垃圾回收器

Hades GC — 是Hermes中的垃圾回收器,专为具有最小暂停的移动场景而设计。与JSC中的mark-sweep GC不同,Hades使用并发(concurrent)回收:回收器与主执行线程并行工作,仅将其暂停短暂时间。Hades GC将堆分为几代:年轻代(nursery)经常快速回收(Scavenge),老年代回收频率较低且暂停时间更短。堆大小可配置:默认为应用程序可用RAM的2/3,最小阈值为32 MB。Hades不使用stop-the-world方法:即使老年代的完整回收也不会超过5-8ms。回收器针对典型的移动场景进行了优化:许多短期对象(临时字符串、React fibre对象),少量长期对象。对于具有密集对象创建的应用程序(列表、动画),与JSC相比,Hades提供更流畅的FPS。

如何在React Native项目中启用Hermes

启用Hermes取决于React Native版本和平台。从React Native 0.70开始,Hermes在新项目中默认对Android启用。对于iOS,Hermes是可选的。在Android上启用:在android/app/build.gradle文件中,在project.ext.react.enableHermes块中设置enableHermes: true。对于iOS:通过use_react_native!(:path => config[:reactNativePath], :hermes_enabled => true)在Podfile中将hermes_enabled设置为true。启用后,执行pod install。对于现有项目,检查库的兼容性:Hermes不支持Proxy、eval和一些ES2021功能。使用npx react-native info检查配置。要在Hermes和JSC之间切换,更改标志并执行clean rebuild。

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不支持:ProxyReflect API(用于MobX、Vue、某些状态管理器),BigInt(大数字),Symbol.toStringTagWeakRefFinalizationRegistry。eval和new Function函数在执行时生成异常。Array.prototype.flatflatMap方法使用this参数的回调在限制下工作。带时区的ISO 8601日期格式未完全处理。这些限制中的大多数不会影响典型的React Native应用程序:React和React Native使用有限的功能集。如果库需要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在开发时会影响热重载吗?

不会,Hermes不会影响热重载/快速刷新。在开发期间,Metro运行JavaScript捆绑包时不进行Hermes编译(纯JS)。Hermes字节码仅为Release版本创建。在Debug模式下,使用标准的JavaScriptCore或Hermes的解释模式。当Hermes在配置中启用时,热重载速度不会改变 — 切换仅在生产构建阶段发生。

Hermes可以与Expo一起使用吗?

可以,从Expo SDK 45开始,Hermes支持managed workflow。在app.json中设置"jsEngine": "hermes"。对于bare workflow,Hermes的工作方式与普通React Native项目相同。Expo Go不支持Hermes — 使用Expo Dev Client或EAS Build进行带Hermes的构建。通过expo doctor检查库的兼容性。

如何在项目中比较Hermes和JSC的性能?

使用React Native Performance Monitor(FPS指标)和Hermes Profiling Tools。在同一设备上构建两个版本 — 带Hermes和JSC。测量:冷启动(从点击图标到第一个交互屏幕)、TTI(Time-To-Interactive)、APK/IPA大小和峰值RAM消耗。对每个配置至少运行3次测试。Hermes的典型优势:启动速度快20-40%,RAM少15-25%。

总结

  • Hermes — Meta的JavaScript引擎,带有用于React Native的AOT编译,从0.70起成为Android标准
  • AOT编译提供可预测的性能,无需在设备上预热JIT
  • 冷启动快20-50%,捆绑包比JavaScriptCore小30-40%
  • Hades GC — 并发垃圾回收器,暂停时间为2-5ms,而JSC为10-20ms
  • 限制:不支持Proxy、BigInt、eval、WeakRef — 检查库
  • 启用:build.gradle中的enableHermes(Android)或Podfile中的hermes_enabled(iOS)
  • Hermes CLI允许编译.hbc字节码并通过DevTools分析内存
  • Hermes在开发时不会影响热重载 — 字节码仅为Release创建

我们将开发一款交钥匙移动应用程序

IT Sectr自2017年以来为初创企业和企业打造iOS和Android应用程序。我们将为您提供咨询并提出最佳解决方案。

讨论项目

另请阅读