Hermes — какво е това, JS двигател за React Native и принцип на работа

Автор: IT Sectr Публикувано: 2026-07-06 Време за четене: 9 мин

Hermes — е JavaScript двигател с AOT компилация (Ahead-of-Time), разработен от Meta за React Native и оптимизиран за мобилни устройства с ограничена памет. Според официалния блог на Meta Engineering (2022), Hermes намалява времето за стартиране на приложението с 20-50% и намалява размера на пакета с 30-40% в сравнение с JavaScriptCore. За разлика от V8 или JSC, Hermes не използва JIT компилация на устройството — целият JavaScript се компилира в байткод на етапа на изграждане чрез Hermes CLI. Това е особено важно за iOS, където JIT компилацията е ограничена от политиките на App Store.

Основни точки

  • Hermes — JavaScript двигател с AOT компилация, разработен от Meta за React Native
  • AOT vs JIT — Hermes компилира JS в байткод на етапа на изграждане, без JIT на устройството
  • Производителност — стартиране на приложението с 20-50% по-бързо, пакет с 30-40% по-малък
  • Hades GC — събирач на отпадъци с ниска латентност, оптимизиран за мобилни сценарии
  • Стандарт — ECMAScript 2020+ без Proxy, BigInt и Reflect в пълен обем

Какво е Hermes

Hermes — е компактен JavaScript двигател с отворен код (MIT лиценз), създаден от 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 и React Native преди версия 0.70. JSC поддържа JIT компилация, което осигурява висока производителност за сложни JavaScript операции. Въпреки това JIT изисква загряване: първите секунди кодът работи по-бавно (интерпретиран режим), след което JIT компилира горещите части. На iOS JIT е практически недостъпен поради политиките на App Store (забрана за динамично генериране на код), така че JSC на iOS работи само в интерпретиран режим — производителността спада. JSC има по-голям двоичен размер (около 10 MB) и консумира повече RAM поради JIT инфраструктурата. Hermes не зависи от JIT, което осигурява предвидима производителност веднага след стартиране (студен старт). JSC поддържа по-пълно стандарта ECMAScript (включително Proxy, BigInt, Reflect), но с цената на по-голяма консумация на ресурси. За React Native проекти, където студеният старт и малкият размер са критични — Hermes е за предпочитане. За проекти с тежки JS изчисления (игри, WebGL) — JSC може да осигури по-висока пикова производителност.

ПараметърHermesJavaScriptCore
КомпилацияAOT (на етапа на изграждане)JIT + Интерпретиран (на устройството)
Студен старт20-50% по-бързБазово ниво
Размер на пакет30-40% по-малъкБазово ниво
Консумация на RAM20-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 runtime зарежда HBC директно, без парсване и компилация. Това радикално ускорява стартирането: вместо да парсва хиляди JS редове (async), двигателят чете предварително компилиран двоичен формат. AOT също намалява размера: байткодът е средно с 30% по-компактен от JavaScript AST. Недостатъкът на 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 Hermes намалява TTI с 34% в сравнение с JSC: от 4.2 секунди на 2.8 секунди на устройство от среден сегмент (Moto G7). Размерът на APK намалява с 28% благодарение на компактния байткод и липсата на JIT библиотеки. Консумацията на 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 паузите до минимум — средно една пауза от 2-5ms на 10 секунди работа срещу паузи от 10-20ms при JSC за същия период.

Събирач на отпадъци Hades GC

Hades GC — е събирачът на отпадъци в Hermes, проектиран за мобилни сценарии с минимални паузи. За разлика от mark-sweep GC в JSC, Hades използва конкурентно (concurrent) събиране: събирачът работи паралелно с основната нишка на изпълнение, спирайки я само за кратки периоди. Hades GC разделя купчината на поколения: младото поколение (nursery) се събира често и бързо (Scavenge), старото поколение се събира по-рядко и с по-малки паузи. Размерът на купчината е конфигурируем: по подразбиране — 2/3 от наличната RAM на приложението, минимален праг — 32 MB. Hades не използва stop-the-world подход: дори пълното събиране на старото поколение отнема не повече от 5-8ms. Събирачът е оптимизиран за типичния мобилен сценарий: много краткоживеещи обекти (временни низове, React fibre обекти), малко дългоживеещи. За приложения с интензивно създаване на обекти (списъци, анимации) Hades осигурява по-плавен FPS в сравнение с JSC.

Как да включите Hermes в React Native проект

Включването на Hermes зависи от версията на React Native и платформата. От React Native 0.70 Hermes е включен по подразбиране за Android в нови проекти. За iOS Hermes е опционален. За включване на Android: във файла android/app/build.gradle задайте enableHermes: true в блока project.ext.react.enableHermes. За iOS: задайте hermes_enabled на true в Podfile чрез use_react_native!(:path => config[:reactNativePath], :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 — включете Hermes на 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: какво не се поддържа

Основните ограничения на Hermes са свързани с отказа от JIT. Hermes не поддържа: Proxy и Reflect API (използвани в MobX, Vue, някои мениджъри на състояние), BigInt (големи числа), Symbol.toStringTag, WeakRef и FinalizationRegistry. Функциите eval и new Function генерират изключение по време на изпълнение. Обратните извиквания на методите Array.prototype.flat и flatMap с аргумент this работят с ограничения. ISO 8601 форматите за дата с часови зони не се обработват напълно. Повечето от тези ограничения не засягат типичните React Native приложения: React и React Native използват ограничен набор от ES функции. Ако библиотека изисква Proxy (например MobX 6+ с Proxy), използвайте 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: Hermes на iOS изисква New Architecture (Fabric Renderer). Задайте :hermes_enabled => true, изпълнете pod install --repo-update. Ако проектът се актуализира от React Native под 0.70, проверете съвместимостта на библиотеките с New Architecture. Изключете Hermes, ако библиотека на трета страна изисква JSC — за целта променете флага на false и преинсталирайте Pods.

Влияе ли Hermes на Hot Reload по време на разработка?

Не, Hermes не влияе на Hot Reload / Fast Refresh. По време на разработка Metro стартира JavaScript пакета без Hermes компилация (обикновен JS). Hermes байткод се създава само за Release версии. В Debug режим се използва стандартен JavaScriptCore или Hermes в интерпретиран режим. Скоростта на Hot Reload не се променя, когато 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 — JavaScript двигател на Meta с AOT компилация за React Native, стандарт на Android от 0.70
  • AOT компилация осигурява предвидима производителност без загряване на JIT на устройството
  • Студен старт 20-50% по-бърз, размер на пакет 30-40% по-малък срещу JavaScriptCore
  • Hades GC — конкурентен събирач на отпадъци с паузи 2-5ms вместо 10-20ms при JSC
  • Ограничения: Proxy, BigInt, eval, WeakRef не се поддържат — проверявайте библиотеките
  • Включване: enableHermes в build.gradle (Android) или hermes_enabled в Podfile (iOS)
  • Hermes CLI позволява компилиране на .hbc байткод и профилиране на паметта чрез DevTools
  • Hermes не влияе на Hot Reload по време на разработка — байткод се създава само за Release

Ще разработим мобилно приложение под ключ

IT Sectr създава iOS и Android приложения за стартъпи и бизнеси от 2017 г. Ще ви консултираме и ще предложим най-доброто решение.

Обсъдете проекта

Прочетете също