Hermes — este un motor JavaScript cu compilare AOT (Ahead-of-Time), dezvoltat de Meta pentru React Native și optimizat pentru dispozitive mobile cu memorie limitată. Conform blogului oficial Meta Engineering (2022), Hermes reduce timpul de pornire a aplicației cu 20-50% și micșorează dimensiunea pachetului cu 30-40% în comparație cu JavaScriptCore. Spre deosebire de V8 sau JSC, Hermes nu folosește compilarea JIT pe dispozitiv — tot JavaScript-ul este compilat în bytecode în etapa de build prin Hermes CLI. Acest lucru este deosebit de important pentru iOS, unde compilarea JIT este restricționată de politicile App Store.
Principalele puncte
Hermes — este un motor JavaScript compact cu sursă deschisă (licența MIT), creat de Meta pentru React Native și optimizat pentru funcționarea pe dispozitive mobile cu resurse limitate. Inovația principală a Hermes este renunțarea la compilarea JIT în favoarea AOT (Ahead-of-Time). În etapa de build a aplicației React Native, Metro Bundler transmite JavaScript-ul compilat către Hermes CLI, care îl transformă în bytecode HBC (Hermes ByteCode). Acest bytecode este executat direct de motor fără compilare suplimentară pe dispozitiv. Această abordare asigură o performanță previzibilă: nu există „încălzire" JIT, nu există pauze de compilare, nu există consum suplimentar de baterie. Hermes a fost proiectat ținând cont de limitările dispozitivelor mobile: RAM redus (1-4 GB), consum limitat de energie și necesitatea unei porniri rapide la rece. Prima lansare publică a Hermes a avut loc în 2019, iar de la React Native 0.70 (2022) motorul a devenit standard pe Android.
JavaScriptCore (JSC) — motorul standard WebKit, utilizat de Safari și React Native înainte de versiunea 0.70. JSC acceptă compilarea JIT, ceea ce oferă performanță ridicată pentru operații complexe JavaScript. Cu toate acestea, JIT necesită încălzire: primele secunde codul rulează mai lent (mod interpretat), apoi JIT compilează secțiunile fierbinți. Pe iOS, JIT este practic indisponibil din cauza politicilor App Store (interdicția generării dinamice de cod), astfel încât JSC pe iOS funcționează doar în mod interpretat — performanța scade. JSC are o dimensiune binară mai mare (aproximativ 10 MB) și consumă mai mult RAM din cauza infrastructurii JIT. Hermes nu depinde de JIT, ceea ce oferă o performanță previzibilă imediat după pornire (pornire la rece). JSC acceptă mai complet standardul ECMAScript (inclusiv Proxy, BigInt, Reflect), dar cu prețul unui consum mai mare de resurse. Pentru proiectele React Native unde pornirea la rece și dimensiunea mică sunt critice — Hermes este preferat. Pentru proiectele cu calcule grele în JS (jocuri, WebGL) — JSC poate oferi o performanță de vârf mai mare.
| Parametru | Hermes | JavaScriptCore |
|---|---|---|
| Compilare | AOT (în etapa de build) | JIT + Interpretat (pe dispozitiv) |
| Pornire la rece | 20-50% mai rapid | Nivel de bază |
| Dimensiune pachet | 30-40% mai mic | Nivel de bază |
| Consum RAM | 20-30% mai puțin | Nivel de bază |
| ECMAScript | ES2020 (limitări) | ES2022+ (complet) |
| iOS JIT | Nu este necesar | Indisponibil (doar interpretat) |
| Binar | ~3 MB | ~10 MB |
Compilarea AOT (Ahead-of-Time) în Hermes are loc în două etape. În prima etapă, Metro Bundler colectează fișierele JavaScript într-un singur pachet și îl transmite către Hermes CLI (utilitarul hermesc). În a doua etapă, hermesc parsează JavaScript AST, generează reprezentarea intermediară HIR (Hermes Intermediate Representation) și apoi emite bytecode-ul binar HBC. Rezultatul este un fișier cu extensia .hbc care conține doar bytecode fără JavaScript-ul original. Hermes runtime încarcă HBC direct, fără parsare și compilare. Acest lucru accelerează radical pornirea: în loc să parseze mii de linii JS (async), motorul citește un format binar precompilat. AOT reduce, de asemenea, dimensiunea: bytecode-ul este în medie cu 30% mai compact decât JavaScript AST. Dezavantajul AOT — imposibilitatea executării eval, new Function sau require dinamic în runtime — toate modulele trebuie să fie cunoscute în etapa de build.
# Instalați Hermes CLI autonom
npm install hermes-engine
# Compilați JS în bytecode HBC
npx hermesc -emit-binary -out bundle.hbc bundle.js
# Statistici bytecode
npx hermesc -dump-bytecode bundle.hbc # shows HBC instructions
# Dimensiunea JS original vs HBC
wc -c bundle.js # 2,300,000 bytes
wc -c bundle.hbc # 1,450,000 bytes (37% reduction)
Performanța Hermes este măsurată după trei metrici cheie: Time-To-Interactive (TTI), dimensiunea APK/IPA și consumul RAM. Conform Meta, pe Android Hermes reduce TTI cu 34% față de JSC: de la 4.2 secunde la 2.8 secunde pe un dispozitiv de segment mediu (Moto G7). Dimensiunea APK se reduce cu 28% datorită bytecode-ului compact și absenței bibliotecilor JIT. Consumul RAM este în medie cu 22% mai mic la aceeași sarcină — acest lucru este deosebit de important pentru dispozitivele cu 2-3 GB RAM. Pe iOS, avantajul este și mai mare: deoarece JSC nu poate folosi JIT, Hermes oferă o creștere a TTI de până la 45%. Metricile se bazează pe testele Meta cu aplicația Facebook Lite. În proiecte reale, avantajul variază: pentru ecrane simple (liste, text) Hermes oferă o creștere mai mare, pentru animații grele — mai mică. Instrument de profilare: React Native Profiler + hermes profile --heap.
Hermes include un profiler de memorie integrat, accesibil prin Chrome DevTools. Conectați-vă la aplicație prin Metro, deschideți fila Memory și selectați Hermes (JavaScript) în tipurile de instantanee. Hermes suportă trei tipuri de instantanee: Heap Snapshot (toate obiectele), Allocation Timeline (durata de viață a obiectelor) și Allocation Sampling (profil selectiv). Hades GC reduce numărul pauzelor GC la minimum — în medie o pauză de 2-5ms la 10 secunde de lucru față de pauzele de 10-20ms la JSC în aceeași perioadă.
Hades GC — este colectorul de gunoi din Hermes, proiectat pentru scenarii mobile cu pauze minime. Spre deosebire de GC mark-sweep din JSC, Hades folosește colectarea concurentă (concurrent): colectorul lucrează paralel cu firul principal de execuție, oprindu-l doar pentru perioade scurte. Hades GC împarte memoria heap în generații: generația tânără (nursery) este colectată frecvent și rapid (Scavenge), generația veche este colectată mai rar și cu pauze mai mici. Dimensiunea heap-ului este configurabilă: implicit — 2/3 din RAM-ul disponibil al aplicației, pragul minim — 32 MB. Hades nu folosește abordarea stop-the-world: chiar și colectarea completă a generației vechi durează cel mult 5-8ms. Colectorul este optimizat pentru scenariul mobil tipic: multe obiecte cu durată scurtă de viață (stringuri temporare, obiecte React fibre), puține obiecte cu durată lungă. Pentru aplicații cu creare intensivă de obiecte (liste, animații) Hades asigură un FPS mai lin în comparație cu JSC.
Activarea Hermes depinde de versiunea React Native și de platformă. Începând cu React Native 0.70, Hermes este activat implicit pentru Android în proiecte noi. Pentru iOS, Hermes este opțional. Pentru activare pe Android: în fișierul android/app/build.gradle setați enableHermes: true în blocul project.ext.react.enableHermes. Pentru iOS: setați hermes_enabled la true în Podfile prin use_react_native!(:path => config[:reactNativePath], :hermes_enabled => true). După activare, executați pod install. Pentru proiecte existente, verificați compatibilitatea bibliotecilor: Hermes nu suportă Proxy, eval și unele funcții ES2021. Folosiți npx react-native info pentru verificarea configurației. Pentru a comuta între Hermes și JSC, modificați flag-ul și executați clean rebuild.
// android/app/build.gradle — activați Hermes
project.ext.react = [
enableHermes: true,
cliPath: "node_modules/react-native/cli.js"
]
// iOS/Podfile — activați Hermes pe 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
Principalele limitări ale Hermes sunt legate de renunțarea la JIT. Hermes nu suportă: Proxy și Reflect API (utilizate în MobX, Vue, unor manageri de stare), BigInt (numere mari), Symbol.toStringTag, WeakRef și FinalizationRegistry. Funcțiile eval și new Function generează excepție în timpul execuției. Callback-urile metodelor Array.prototype.flat și flatMap cu argumentul this funcționează cu limitări. Formatele de date ISO 8601 cu fusuri orare nu sunt procesate complet. Majoritatea acestor limitări nu afectează aplicațiile tipice React Native: React și React Native folosesc un set limitat de funcții ES. Dacă o bibliotecă necesită Proxy (de exemplu, MobX 6+ cu Proxy), utilizați configure({ useProxies: false }) sau alegeți o alternativă. Pentru verificarea compatibilității codului existent, rulați npx hermesc -check pe pachetul dvs. — va afișa lista funcțiilor neacceptate.
Întrebări frecvente
În consola aplicației executați console.log(global.HermesInternal). Dacă obiectul HermesInternal există — aplicația rulează pe Hermes. Alternativ: console.log(global.HermesInternal?.getRuntimeProperties()) — va afișa versiunea motorului și parametrii GC. În versiunile Release, HermesInternal poate fi indisponibil pentru minimizarea dimensiunii.
Verificați setările Podfile: Hermes pe iOS necesită New Architecture (Fabric Renderer). Setați :hermes_enabled => true, executați pod install --repo-update. Dacă proiectul este actualizat de la React Native sub 0.70, verificați compatibilitatea bibliotecilor cu New Architecture. Dezactivați Hermes dacă o bibliotecă terță necesită JSC — pentru aceasta modificați flag-ul la false și reinstalați Pods.
Nu, Hermes nu afectează Hot Reload / Fast Refresh. În timpul dezvoltării, Metro rulează pachetul JavaScript fără compilare Hermes (plain JS). Bytecode-ul Hermes este creat doar pentru versiunile Release. În modul Debug se folosește JavaScriptCore standard sau Hermes în mod interpretat. Viteza Hot Reload nu se modifică atunci când Hermes este activat în configurație — comutarea are loc doar în etapa de build de producție.
Da, începând cu Expo SDK 45, Hermes este suportat pentru managed workflow. În app.json setați "jsEngine": "hermes". Pentru bare workflow, Hermes funcționează ca într-un proiect React Native obișnuit. Expo Go nu suportă Hermes — utilizați Expo Dev Client sau EAS Build pentru versiunile cu Hermes. Verificați compatibilitatea bibliotecilor prin expo doctor.
Utilizați React Native Performance Monitor (metrici FPS) și Hermes Profiling Tools. Construiți două versiuni ale aplicației — cu Hermes și JSC — pe același dispozitiv. Măsurați: pornirea la rece (de la clic pe pictogramă până la primul ecran interactiv), TTI (Time-To-Interactive), dimensiunea APK/IPA și consumul maxim de RAM. Rulați testele de cel puțin 3 ori pentru fiecare configurație. Avantajul tipic al Hermes: pornire cu 20-40% mai rapidă, RAM cu 15-25% mai puțin.
Rezumat
Vom dezvolta o aplicație mobilă la cheie
IT Sectr creează aplicații iOS și Android pentru startup-uri și afaceri din 2017. Vă vom consilia și vă vom propune cea mai bună soluție.
Citiți și