Hermes est un moteur JavaScript avec compilation AOT (Ahead-of-Time), développé par Meta pour React Native et optimisé pour les appareils mobiles à mémoire limitée. Selon le blog officiel de Meta Engineering (2022), Hermes réduit le temps de démarrage de l'application de 20 à 50 % et diminue la taille du bundle de 30 à 40 % par rapport à JavaScriptCore. Contrairement à V8 ou JSC, Hermes n'utilise pas la compilation JIT sur l'appareil — tout le JavaScript est compilé en bytecode lors de la phase de build via Hermes CLI. Ceci est particulièrement important pour iOS, où la compilation JIT est restreinte par les politiques de l'App Store.
Points clés
Hermes est un moteur JavaScript compact open source (licence MIT) créé par Meta pour React Native et optimisé pour fonctionner sur les appareils mobiles aux ressources limitées. La principale innovation de Hermes est d'abandonner la compilation JIT au profit de l'AOT (Ahead-of-Time). Pendant la phase de build de l'application React Native, Metro Bundler transmet le JavaScript compilé à Hermes CLI, qui le transforme en bytecode HBC (Hermes ByteCode). Ce bytecode est exécuté directement par le moteur sans compilation supplémentaire sur l'appareil. Cette approche offre des performances prévisibles : pas d'échauffement JIT, pas de pauses de compilation, pas de consommation de batterie supplémentaire. Hermes est conçu en tenant compte des limites des appareils mobiles : peu de RAM (1-4 Go), consommation d'énergie limitée et nécessité d'un démarrage à froid rapide. La première version publique de Hermes a eu lieu en 2019 et, à partir de React Native 0.70 (2022), le moteur est devenu le standard sur Android.
JavaScriptCore (JSC) est le moteur WebKit standard utilisé par Safari et React Native avant la version 0.70. JSC prend en charge la compilation JIT, ce qui offre des performances élevées pour les opérations JavaScript complexes. Cependant, JIT nécessite un échauffement : les premières secondes d'exécution sont plus lentes (mode interprété), puis JIT compile les chemins chauds. Sur iOS, JIT est pratiquement indisponible en raison des politiques de l'App Store (interdiction de génération dynamique de code), donc JSC sur iOS fonctionne uniquement en mode interprété — les performances chutent. JSC a une taille binaire plus grande (environ 10 Mo) et consomme plus de RAM en raison de l'infrastructure JIT. Hermes ne dépend pas de JIT, offrant des performances prévisibles immédiatement après le démarrage (démarrage à froid). JSC supporte plus complètement le standard ECMAScript (y compris Proxy, BigInt, Reflect), mais au prix d'une consommation de ressources plus élevée. Pour les projets React Native où le démarrage à froid et la petite taille sont critiques — Hermes est préférable. Pour les projets avec des calculs JS lourds (jeux, WebGL) — JSC peut offrir des performances de pointe plus élevées.
| Paramètre | Hermes | JavaScriptCore |
|---|---|---|
| Compilation | AOT (au build) | JIT + Interprété (sur l'appareil) |
| Démarrage à froid | 20-50 % plus rapide | Niveau de base |
| Taille du bundle | 30-40 % plus petite | Niveau de base |
| Consommation RAM | 20-30 % moins | Niveau de base |
| ECMAScript | ES2020 (limitations) | ES2022+ (complet) |
| JIT iOS | Non requis | Indisponible (interprété seulement) |
| Binaire | ~3 Mo | ~10 Mo |
La compilation AOT (Ahead-of-Time) dans Hermes se déroule en deux étapes. Dans la première étape, Metro Bundler rassemble les fichiers JavaScript en un seul bundle et le transmet à Hermes CLI (l'utilitaire hermesc). Dans la deuxième étape, hermesc analyse l'AST JavaScript, génère une représentation intermédiaire HIR (Hermes Intermediate Representation) puis émet du bytecode HBC binaire. Le résultat est un fichier .hbc qui contient uniquement le bytecode sans le JavaScript d'origine. L'environnement d'exécution Hermes charge HBC directement, sans analyse ni compilation. Cela accélère radicalement le démarrage : au lieu d'analyser des milliers de lignes de JS (async), le moteur lit un format binaire précompilé. L'AOT réduit également la taille : le bytecode est en moyenne 30 % plus compact que l'AST JavaScript. L'inconvénient de l'AOT — l'impossibilité d'exécuter eval, new Function ou require dynamique à l'exécution — tous les modules doivent être connus au moment du build.
# Installer Hermes CLI autonome
npm install hermes-engine
# Compiler JS en bytecode HBC
npx hermesc -emit-binary -out bundle.hbc bundle.js
# Statistiques du bytecode
npx hermesc -dump-bytecode bundle.hbc # shows HBC instructions
# Taille JS original vs HBC
wc -c bundle.js # 2,300,000 bytes
wc -c bundle.hbc # 1,450,000 bytes (37% reduction)
Les performances de Hermes sont mesurées par trois métriques clés : le Time-To-Interactive (TTI), la taille de l'APK/IPA et la consommation de RAM. Selon les données de Meta, sur Android Hermes réduit le TTI de 34 % par rapport à JSC : de 4,2 secondes à 2,8 secondes sur un appareil de milieu de gamme (Moto G7). La taille de l'APK diminue de 28 % grâce au bytecode compact et à l'absence de bibliothèques JIT. La consommation de RAM est en moyenne 22 % inférieure sous la même charge — ceci est particulièrement important pour les appareils avec 2-3 Go de RAM. Sur iOS, le gain est encore plus significatif : puisque JSC ne peut pas utiliser JIT, Hermes offre une amélioration du TTI allant jusqu'à 45 %. Les métriques sont basées sur des tests de Meta avec l'application Facebook Lite. Dans les projets réels, le gain varie : pour les écrans simples (listes, texte) Hermes apporte une plus grande amélioration, pour les animations lourdes — moindre. Outil de profilage : React Native Profiler + hermes profile --heap.
Hermes inclut un profileur de mémoire intégré accessible via Chrome DevTools. Connectez-vous à l'application via Metro, ouvrez l'onglet Mémoire et sélectionnez Hermes (JavaScript) dans les types d'instantanés. Hermes prend en charge trois types d'instantanés : Heap Snapshot (tous les objets), Allocation Timeline (durée de vie des objets) et Allocation Sampling (profil par échantillonnage). Hades GC réduit les pauses du GC au minimum — en moyenne une pause de 2-5 ms pour 10 secondes de fonctionnement, contre des pauses de 10-20 ms pour JSC sur la même période.
Hades GC est le ramasse-miettes de Hermes, conçu pour les scénarios mobiles avec des pauses minimales. Contrairement au GC mark-sweep de JSC, Hades utilise une collecte concurrente : le collecteur travaille en parallèle avec le thread d'exécution principal, ne l'arrêtant que pour de courts intervalles. Hades GC divise le tas en générations : la jeune génération (nursery) est collectée fréquemment et rapidement (Scavenge), la vieille génération est collectée moins souvent avec des pauses plus courtes. La taille du tas est configurable : par défaut — 2/3 de la RAM disponible de l'application, seuil minimum — 32 Mo. Hades n'utilise pas l'approche stop-the-world : même une collecte complète de la vieille génération ne prend pas plus de 5-8 ms. Le collecteur est optimisé pour les scénarios mobiles typiques : beaucoup d'objets à courte durée de vie (chaînes temporaires, objets React fiber), peu d'objets à longue durée de vie. Pour les applications avec création intensive d'objets (listes, animations), Hades offre des FPS plus fluides par rapport à JSC.
L'activation de Hermes dépend de la version de React Native et de la plateforme. À partir de React Native 0.70, Hermes est activé par défaut pour Android dans les nouveaux projets. Pour iOS, Hermes est optionnel. Pour activer sur Android : dans le fichier android/app/build.gradle définissez enableHermes : true dans le bloc project.ext.react.enableHermes. Pour iOS : définissez hermes_enabled sur true dans le Podfile via use_react_native!(:path => config[:reactNativePath], :hermes_enabled => true). Après activation, exécutez pod install. Pour les projets existants, vérifiez la compatibilité des bibliothèques : Hermes ne supporte pas Proxy, eval et certaines fonctionnalités ES2021. Utilisez npx react-native info pour vérifier la configuration. Pour basculer entre Hermes et JSC, modifiez le flag et effectuez une reconstruction propre.
// android/app/build.gradle — activer Hermes
project.ext.react = [
enableHermes: true,
cliPath: "node_modules/react-native/cli.js"
]
// iOS/Podfile — activer Hermes sur 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
Les principales limitations de Hermes sont liées à l'absence de JIT. Hermes ne supporte pas : Proxy et Reflect API (utilisés dans MobX, Vue, certains gestionnaires d'état), BigInt (grands nombres), Symbol.toStringTag, WeakRef et FinalizationRegistry. Les fonctions eval et new Function génèrent une exception à l'exécution. Les callbacks des méthodes Array.prototype.flat et flatMap avec un argument this fonctionnent avec des limitations. Les formats de date ISO 8601 avec fuseaux horaires ne sont pas entièrement traités. La plupart de ces limitations n'affectent pas les applications React Native typiques : React et React Native utilisent un ensemble limité de fonctionnalités ES. Si une bibliothèque nécessite Proxy (par exemple, MobX 6+ avec Proxy), utilisez configure({ useProxies : false }) ou choisissez une alternative. Pour vérifier la compatibilité du code existant, exécutez npx hermesc -check sur votre bundle — il affichera la liste des fonctionnalités non supportées.
Questions fréquentes
Dans la console de l'application, exécutez console.log(global.HermesInternal). Si l'objet HermesInternal existe — l'application fonctionne sur Hermes. Alternativement : console.log(global.HermesInternal?.getRuntimeProperties()) — affichera la version du moteur et les paramètres GC. Dans les builds Release, HermesInternal peut ne pas être disponible pour minimiser la taille.
Vérifiez les paramètres de votre Podfile : Hermes sur iOS nécessite New Architecture (Fabric Renderer). Définissez :hermes_enabled => true, exécutez pod install --repo-update. Si le projet est mis à jour depuis React Native inférieur à 0.70, vérifiez la compatibilité des bibliothèques avec New Architecture. Désactivez Hermes si une bibliothèque tierce nécessite JSC — modifiez le flag à false et réinstallez les Pods.
Non, Hermes n'affecte pas le Hot Reload / Fast Refresh. Pendant le développement, Metro exécute le bundle JavaScript sans compilation Hermes (JS pur). Le bytecode Hermes est compilé uniquement pour les builds Release. En mode Debug, JavaScriptCore standard ou Hermes en mode interprété est utilisé. La vitesse du Hot Reload ne change pas lorsque Hermes est activé dans la configuration — le basculement se produit uniquement à l'étape du build de production.
Oui, à partir d'Expo SDK 45, Hermes est supporté pour le managed workflow. Dans app.json, spécifiez "jsEngine" : "hermes". Pour le bare workflow, Hermes fonctionne comme dans un projet React Native normal. Expo Go ne supporte pas Hermes — utilisez Expo Dev Client ou EAS Build pour les builds avec Hermes. Vérifiez la compatibilité des bibliothèques via expo doctor.
Utilisez React Native Performance Monitor (métriques FPS) et Hermes Profiling Tools. Créez deux versions de l'application — avec Hermes et JSC — sur le même appareil. Mesurez : le démarrage à froid (du tap sur l'icône au premier écran interactif), le TTI (Time-To-Interactive), la taille APK/IPA et la consommation maximale de RAM. Exécutez les tests au moins 3 fois pour chaque configuration. Avantage typique de Hermes : démarrage 20-40 % plus rapide, RAM 15-25 % moins élevée.
Résumé
Nous développerons une application mobile clé en main
IT Sectr crée des applications iOS et Android pour les startups et les entreprises depuis 2017. Nous vous conseillerons et vous proposerons la meilleure solution.
Lisez aussi