Hermes — cos'è, motore JS per React Native e principio di funzionamento

Autore: IT Sectr Pubblicato: 2026-07-06 Tempo di lettura: 9 min

Hermes è un motore JavaScript con compilazione AOT (Ahead-of-Time), sviluppato da Meta per React Native e ottimizzato per dispositivi mobili con memoria limitata. Secondo il blog ufficiale di Meta Engineering (2022), Hermes riduce il tempo di avvio dell'app del 20-50% e diminuisce la dimensione del bundle del 30-40% rispetto a JavaScriptCore. A differenza di V8 o JSC, Hermes non utilizza la compilazione JIT sul dispositivo — tutto il JavaScript viene compilato in bytecode durante la fase di build tramite Hermes CLI. Questo è particolarmente importante per iOS, dove la compilazione JIT è limitata dalle politiche dell'App Store.

Punti chiave

  • Hermes — un motore JavaScript con compilazione AOT, sviluppato da Meta per React Native
  • AOT vs JIT — Hermes compila JS in bytecode al build, senza JIT sul dispositivo
  • Prestazioni — avvio app 20-50% più veloce, bundle 30-40% più piccolo
  • Hades GC — garbage collector a bassa latenza ottimizzato per scenari mobili
  • Standard — ECMAScript 2020+ senza supporto completo di Proxy, BigInt e Reflect

Cos'è Hermes

Hermes è un motore JavaScript compatto open source (licenza MIT) creato da Meta per React Native e ottimizzato per funzionare su dispositivi mobili con risorse limitate. L'innovazione principale di Hermes è l'abbandono della compilazione JIT in favore di AOT (Ahead-of-Time). Durante la fase di build dell'app React Native, Metro Bundler passa il JavaScript compilato a Hermes CLI, che lo trasforma in bytecode HBC (Hermes ByteCode). Questo bytecode viene eseguito direttamente dal motore senza compilazione aggiuntiva sul dispositivo. Questo approccio fornisce prestazioni prevedibili: nessun riscaldamento JIT, nessuna pausa di compilazione, nessun consumo extra della batteria. Hermes è progettato tenendo conto dei limiti dei dispositivi mobili: poca RAM (1-4 GB), consumo energetico limitato e necessità di un avvio a freddo rapido. La prima versione pubblica di Hermes è stata nel 2019 e, a partire da React Native 0.70 (2022), il motore è diventato lo standard su Android.

Hermes vs JavaScriptCore: confronto motori

JavaScriptCore (JSC) è il motore WebKit standard utilizzato da Safari e React Native prima della versione 0.70. JSC supporta la compilazione JIT, che offre prestazioni elevate per operazioni JavaScript complesse. Tuttavia, JIT richiede riscaldamento: i primi secondi di esecuzione sono più lenti (modalità interpretata), poi JIT compila i percorsi caldi. Su iOS, JIT è praticamente indisponibile a causa delle politiche dell'App Store (divieto di generazione dinamica di codice), quindi JSC su iOS funziona solo in modalità interpretata — le prestazioni calano. JSC ha una dimensione binaria maggiore (circa 10 MB) e consuma più RAM a causa dell'infrastruttura JIT. Hermes non dipende da JIT, fornendo prestazioni prevedibili immediatamente dopo l'avvio (cold start). JSC supporta lo standard ECMAScript in modo più completo (inclusi Proxy, BigInt, Reflect), ma a costo di un maggiore consumo di risorse. Per i progetti React Native dove l'avvio a freddo e le dimensioni ridotte sono critici — Hermes è preferibile. Per progetti con calcoli JS pesanti (giochi, WebGL) — JSC può offrire prestazioni di picco più elevate.

ParametroHermesJavaScriptCore
CompilazioneAOT (al build)JIT + Interpretato (sul dispositivo)
Cold start20-50% più veloceLivello base
Dimensione bundle30-40% più piccolaLivello base
Consumo RAM20-30% in menoLivello base
ECMAScriptES2020 (limitazioni)ES2022+ (completo)
JIT iOSNon richiestoNon disponibile (solo interpretato)
Binario~3 MB~10 MB

Compilazione AOT: come funziona la precompilazione

La compilazione AOT (Ahead-of-Time) in Hermes avviene in due fasi. Nella prima fase, Metro Bundler raccoglie i file JavaScript in un unico bundle e lo passa a Hermes CLI (l'utilità hermesc). Nella seconda fase, hermesc analizza l'AST JavaScript, genera una rappresentazione intermedia HIR (Hermes Intermediate Representation) e quindi emette bytecode HBC binario. Il risultato è un file .hbc che contiene solo bytecode senza il JavaScript originale. Il runtime di Hermes carica HBC direttamente, senza analisi e compilazione. Questo accelera radicalmente l'avvio: invece di analizzare migliaia di righe di JS (async), il motore legge un formato binario precompilato. AOT riduce anche le dimensioni: il bytecode è in media il 30% più compatto dell'AST JavaScript. Lo svantaggio di AOT — l'impossibilità di eseguire eval, new Function o require dinamico in fase di esecuzione — tutti i moduli devono essere noti al momento del build.

bash
# Installare Hermes CLI standalone
npm install hermes-engine

# Compilare JS in bytecode HBC
npx hermesc -emit-binary -out bundle.hbc bundle.js

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

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

Metriche di prestazione di Hermes

Le prestazioni di Hermes sono misurate da tre metriche chiave: Time-To-Interactive (TTI), dimensione APK/IPA e consumo di RAM. Secondo i dati di Meta, su Android Hermes riduce il TTI del 34% rispetto a JSC: da 4,2 secondi a 2,8 secondi su un dispositivo di fascia media (Moto G7). La dimensione dell'APK diminuisce del 28% grazie al bytecode compatto e all'assenza di librerie JIT. Il consumo di RAM è in media inferiore del 22% a parità di carico — questo è particolarmente importante per i dispositivi con 2-3 GB di RAM. Su iOS, il vantaggio è ancora più significativo: poiché JSC non può utilizzare JIT, Hermes fornisce un miglioramento del TTI fino al 45%. Le metriche si basano su test di Meta con l'app Facebook Lite. Nei progetti reali, il vantaggio varia: per schermate semplici (liste, testo) Hermes offre un miglioramento maggiore, per animazioni pesanti — minore. Strumento di profilazione: React Native Profiler + hermes profile --heap.

Profilazione della memoria con Hermes

Hermes include un profilatore di memoria integrato accessibile tramite Chrome DevTools. Connettiti all'app tramite Metro, apri la scheda Memoria e seleziona Hermes (JavaScript) nei tipi di snapshot. Hermes supporta tre tipi di snapshot: Heap Snapshot (tutti gli oggetti), Allocation Timeline (durata degli oggetti) e Allocation Sampling (profilo a campione). Hades GC riduce le pause del GC al minimo — in media una pausa di 2-5ms ogni 10 secondi di funzionamento, contro pause di 10-20ms per JSC nello stesso periodo.

Garbage Collector Hades GC

Hades GC è il garbage collector di Hermes, progettato per scenari mobili con pause minime. A differenza del GC mark-sweep in JSC, Hades utilizza la raccolta concorrente: il collector lavora in parallelo con il thread di esecuzione principale, fermandolo solo per brevi intervalli. Hades GC divide l'heap in generazioni: la generazione giovane (nursery) viene raccolta frequentemente e rapidamente (Scavenge), la generazione vecchia viene raccolta meno spesso e con pause più brevi. La dimensione dell'heap è configurabile: per impostazione predefinita — 2/3 della RAM disponibile dell'app, soglia minima — 32 MB. Hades non utilizza l'approccio stop-the-world: anche una raccolta completa della generazione vecchia non richiede più di 5-8ms. Il collector è ottimizzato per scenari mobili tipici: molti oggetti a vita breve (stringhe temporanee, oggetti React fiber), pochi a vita lunga. Per applicazioni con creazione intensiva di oggetti (liste, animazioni), Hades fornisce FPS più fluidi rispetto a JSC.

Come abilitare Hermes in un progetto React Native

L'abilitazione di Hermes dipende dalla versione di React Native e dalla piattaforma. A partire da React Native 0.70, Hermes è abilitato per impostazione predefinita per Android nei nuovi progetti. Per iOS, Hermes è opzionale. Per abilitare su Android: nel file android/app/build.gradle imposta enableHermes: true nel blocco project.ext.react.enableHermes. Per iOS: imposta hermes_enabled su true nel Podfile tramite use_react_native!(:path => config[:reactNativePath], :hermes_enabled => true). Dopo l'abilitazione, esegui pod install. Per progetti esistenti, verifica la compatibilità delle librerie: Hermes non supporta Proxy, eval e alcune funzionalità ES2021. Usa npx react-native info per verificare la configurazione. Per passare da Hermes a JSC, modifica il flag ed esegui una ricostruzione pulita.

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

// iOS/Podfile — abilitare Hermes su 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

Limitazioni di Hermes: cosa non è supportato

Le principali limitazioni di Hermes sono legate all'assenza di JIT. Hermes non supporta: Proxy e Reflect API (usati in MobX, Vue, alcuni state manager), BigInt (numeri grandi), Symbol.toStringTag, WeakRef e FinalizationRegistry. Le funzioni eval e new Function generano un'eccezione in fase di esecuzione. I callback dei metodi Array.prototype.flat e flatMap con un argomento this funzionano con limitazioni. I formati di data ISO 8601 con fusi orari non vengono elaborati completamente. La maggior parte di queste limitazioni non influisce sulle applicazioni React Native tipiche: React e React Native utilizzano un insieme limitato di funzionalità ES. Se una libreria richiede Proxy (ad esempio, MobX 6+ con Proxy), usa configure({ useProxies: false }) o scegli un'alternativa. Per verificare la compatibilità del codice esistente, esegui npx hermesc -check sul tuo bundle — mostrerà l'elenco delle funzionalità non supportate.

  • Proxy / Reflect — non implementati; le librerie che richiedono Proxy necessitano di modalità fallback
  • BigInt — non disponibile; usa librerie bignumber.js per numeri grandi
  • eval / new Function — lancia eccezione; tutti i moduli devono essere statici
  • WeakRef / FinalizationRegistry — non supportati; nessuna alternativa
  • Symbol.toStringTag — ignorato; instanceof funziona correttamente

Domande frequenti

Come verificare se l'app funziona su Hermes?

Nella console dell'app, esegui console.log(global.HermesInternal). Se l'oggetto HermesInternal esiste — l'app funziona su Hermes. In alternativa: console.log(global.HermesInternal?.getRuntimeProperties()) — mostrerà la versione del motore e i parametri GC. Nelle build Release, HermesInternal potrebbe non essere disponibile per ridurre le dimensioni.

Perché l'app si blocca su iOS dopo aver abilitato Hermes?

Controlla le impostazioni del Podfile: Hermes su iOS richiede New Architecture (Fabric Renderer). Imposta :hermes_enabled => true, esegui pod install --repo-update. Se il progetto viene aggiornato da React Native inferiore a 0.70, verifica la compatibilità delle librerie con New Architecture. Disabilita Hermes se una libreria di terze parti richiede JSC — imposta il flag su false e reinstalla i Pods.

Hermes influisce su Hot Reload durante lo sviluppo?

No, Hermes non influisce su Hot Reload / Fast Refresh. Durante lo sviluppo, Metro esegue il bundle JavaScript senza compilazione Hermes (JS puro). Il bytecode Hermes viene compilato solo per le build Release. In modalità Debug, viene utilizzato JavaScriptCore standard o Hermes in modalità interpretata. La velocità di Hot Reload non cambia quando Hermes è abilitato nella configurazione — il passaggio avviene solo nella fase di build di produzione.

Si può usare Hermes con Expo?

, a partire da Expo SDK 45, Hermes è supportato per managed workflow. In app.json specifica "jsEngine": "hermes". Per bare workflow, Hermes funziona come in un normale progetto React Native. Expo Go non supporta Hermes — usa Expo Dev Client o EAS Build per build con Hermes. Verifica la compatibilità delle librerie tramite expo doctor.

Come confrontare le prestazioni di Hermes e JSC nel mio progetto?

Usa React Native Performance Monitor (metriche FPS) e Hermes Profiling Tools. Crea due versioni dell'app — con Hermes e JSC — sullo stesso dispositivo. Misura: cold start (dal tocco sull'icona al primo schermo interattivo), TTI (Time-To-Interactive), dimensione APK/IPA e consumo massimo di RAM. Esegui i test almeno 3 volte per ogni configurazione. Vantaggio tipico di Hermes: avvio 20-40% più veloce, RAM 15-25% inferiore.

Riepilogo

  • Hermes — un motore JavaScript di Meta con compilazione AOT per React Native, standard su Android da 0.70
  • Compilazione AOT offre prestazioni prevedibili senza riscaldamento JIT sul dispositivo
  • Cold start 20-50% più veloce, dimensione bundle 30-40% inferiore vs JavaScriptCore
  • Hades GC — garbage collector concorrente con pause di 2-5ms invece di 10-20ms per JSC
  • Limitazioni: Proxy, BigInt, eval, WeakRef non supportati — verifica le tue librerie
  • Abilitazione: enableHermes in build.gradle (Android) o hermes_enabled in Podfile (iOS)
  • Hermes CLI consente di compilare bytecode .hbc e profilare la memoria tramite DevTools
  • Hermes non influisce su Hot Reload in sviluppo — il bytecode viene compilato solo per Release

Svilupperemo un'applicazione mobile chiavi in mano

IT Sectr crea applicazioni iOS e Android per startup e aziende dal 2017. Ti consulteremo e ti proporremo la soluzione migliore.

Discuti il progetto

Leggi anche