Chapitre 1.2 — Comment ça marche : du JS au pixel natif
Où on en est : vous savez pourquoi React Native. Ce chapitre ouvre le capot une bonne fois pour toutes — ensuite, chaque message d’erreur, chaque question de perf, chaque choix de lib se rattachera à ce schéma.
⏱️ TL;DR — Votre code React est compilé en bytecode et exécuté par Hermes, le moteur JS embarqué dans l’app, sur un thread JavaScript séparé du thread UI. Il communique avec le monde natif via JSI (des appels C++ directs, plus de sérialisation JSON). Fabric projette votre arbre React en widgets natifs ; les TurboModules exposent les APIs système (caméra, stockage…). L’ensemble = la New Architecture, active par défaut depuis RN 0.76.
🎯 Objectifs
- Visualiser les 3 acteurs : thread JS (Hermes), thread UI natif, et JSI entre les deux.
- Comprendre ce que Fabric fait de votre JSX, et où sont calculés les layouts (Yoga).
- Savoir ce qu’était « le bridge » et pourquoi la New Architecture l’a remplacé.
- Comprendre ce qu’est un bundle JS — la clé qui rendra les mises à jour OTA évidentes (Partie 12).
Le navigateur en moins, un moteur JS en plus
Sur le web, votre React tourne dans le moteur JS du navigateur (V8, JavaScriptCore) et manipule le DOM. Sur mobile, il n’y a pas de navigateur. React Native embarque donc son propre moteur JavaScript dans l’app : Hermes, développé par Meta spécifiquement pour le mobile.
Particularité clé : avec Hermes, votre JS est compilé en bytecode au moment du build, pas parsé au lancement. Résultat : démarrage nettement plus rapide et moins de mémoire — sur mobile, chaque milliseconde de démarrage compte.
💡 Pour un dev Next.js — Transposition rapide : Hermes ≈ le V8 de votre navigateur ; Fabric ≈ React DOM (le renderer) ; les widgets natifs ≈ le DOM ; JSI ≈ rien d’équivalent — c’est le pont entre deux mondes qui n’existe pas sur le web, où tout vit déjà dans le navigateur. Et le thread JS séparé ressemble à un Web Worker qui piloterait la page.
Les deux mondes et leurs threads
Une app RN vit sur (au moins) deux threads :
- Le thread JS : exécute votre code React — vos composants, hooks, votre logique de score Drill. C’est un seul thread, comme sur le web : un calcul lourd ici gèle votre logique (mais pas forcément l’UI, on y revient avec Reanimated en Partie 10).
- Le thread UI (natif) : celui où Android dessine, scrolle, répond au doigt. Il ne sait rien de React.
La performance d’une app RN se joue presque toujours au même endroit : combien de fois et avec quel volume ces deux mondes se parlent. Gardez ce réflexe dès maintenant — il expliquera les règles de FlatList (Partie 3), de Reanimated (Partie 10) et la plupart des conseils perf.
JSI : la fin du « bridge »
Jusqu’en ~2022, RN utilisait le bridge : chaque échange JS ↔ natif était sérialisé en JSON, envoyé de façon asynchrone par lots, désérialisé de l’autre côté. Ça marchait, mais : files d’attente saturées lors des gros scrolls, impossibilité d’appels synchrones, coût de sérialisation permanent. C’est la source de 90 % des articles « React Native est lent » que vous pouvez encore croiser.
La New Architecture remplace ce bridge par JSI (JavaScript Interface) : une couche C++ qui permet au JS de tenir des références directes vers des objets natifs et de les appeler comme des fonctions, y compris de façon synchrone quand c’est nécessaire. Plus de JSON, plus de file d’attente.
Sur cette fondation, deux systèmes :
- Fabric — le nouveau renderer. Il prend l’arbre que React produit (le même travail de réconciliation que sur le web), calcule le layout via Yoga (l’implémentation C++ de flexbox — voilà pourquoi RN « parle flexbox », Partie 4), puis crée/met à jour les widgets natifs.
- TurboModules — les modules d’APIs système (stockage, caméra, notifications…), chargés à la demande (lazy) au lieu de tous au démarrage.
⚡ Depuis RN 0.76 — La New Architecture est activée par défaut ; avec Expo SDK 57 / RN 0.86, l’ancienne architecture est en fin de vie. Concrètement pour vous : rien à configurer, mais si vous tombez sur un article ou une lib qui parle du « bridge », de
NativeModulesou mesure des perfs pré-2023 — il est périmé. Réflexe : vérifier la date et la compatibilité New Architecture d’une lib avant de l’adopter.
Le voyage d’un setState
Déroulons ce qui se passe quand, dans Drill, le joueur touche une réponse :
// app/(tabs)/quiz.tsx — extrait anticipé de Drill (Partie 6)
const [status, setStatus] = useState<'playing' | 'answered'>('playing')
<Pressable onPress={() => setStatus('answered')}>
<Text>Symfony est sorti en 2005</Text>
</Pressable>- Thread UI : Android détecte le toucher sur le widget natif.
- Fabric → JSI → Hermes : l’événement remonte au thread JS, qui exécute votre
onPress. - Thread JS :
setStatusdéclenche un re-render React — réconciliation, exactement comme sur le web. React produit un nouvel arbre « virtuel ». - Fabric : calcule le diff, demande à Yoga les nouveaux layouts, puis applique les changements minimaux aux widgets natifs.
- Thread UI : Android redessine les vues modifiées. Le doigt de l’utilisateur voit le feedback.
Votre modèle mental React (étape 3) est inchangé. Ce cours vous apprend surtout à bien vivre avec les étapes 1-2 et 4-5.
Le bundle JS — retenez bien celui-là
Au build, Metro (le bundler de RN, l’équivalent de webpack/Turbopack) assemble tout votre code et ses dépendances en un fichier bundle, compilé en bytecode Hermes, embarqué dans l’APK à côté du code natif :
Conséquence énorme, qu’on exploitera en Partie 12 : le code natif ne change que quand vous ajoutez des modules natifs — votre code applicatif, lui, vit dans le bundle JS. Or un bundle peut être remplacé sans réinstaller l’app : c’est le principe des mises à jour OTA (EAS Update). Corriger un bug de Drill sans toucher au Play Store ni régénérer d’APK : possible précisément grâce à cette séparation.
⚠️ Piège — « React Native, c’est du JS, donc c’est interprété donc lent. » Doublement faux en 2026 : Hermes exécute du bytecode précompilé, et les opérations coûteuses (layout, rendu, animations Reanimated) tournent côté C++/natif. Le JS n’est que le chef d’orchestre — et un chef d’orchestre n’a pas besoin de courir vite.
🍏 Côté iOS — Architecture strictement identique : Hermes, JSI, Fabric, mêmes threads. Seule la cible change :
UILabelau lieu deTextView. C’est toute la beauté du système — et la raison pour laquelle « Android-first » ne vous enferme nulle part.
✏️ Exercices
1. Dessinez de mémoire (papier ou tête) le schéma : thread JS, JSI, Fabric, TurboModules, thread UI. Placez « votre code React » et « TextView ».
✅ Solution
Votre code React (bytecode Hermes) tourne sur le thread JS. Il parle via JSI (C++,
appels directs) à deux familles natives : Fabric (rendu — projette l’arbre React en widgets
et fait calculer le layout par Yoga) et TurboModules (APIs système). Fabric pilote le
thread UI Android, où vivent les TextView/ViewGroup réellement affichés.
2. Votre app calcule les statistiques de 10 000 sessions Drill dans une boucle JS serrée. Quel thread est bloqué, et l’utilisateur peut-il encore scroller la liste affichée ?
✅ Solution
Le thread JS est bloqué : plus aucun onPress, setState ou logique React ne s’exécute.
Le scroll natif, lui, continue en général de fonctionner (il est géré par le thread UI),
mais tout ce qui dépend du JS — nouveaux items d’une FlatList qui se charge, réactions aux taps —
gèle. Leçon : le gros calcul se déplace (SQL en Partie 8) ou se découpe.
3. Expliquez en deux phrases pourquoi une mise à jour OTA peut corriger un bug de logique de
score, mais pas ajouter la lib expo-camera.
✅ Solution
L’OTA remplace uniquement le bundle JS embarqué. La logique de score est du JS → remplaçable.
expo-camera ajoute du code natif compilé dans l’APK → il faut un nouveau build et une
réinstallation. (Le contrat exact — runtime version — arrive en Partie 12.)
🧠 Quiz
1. Quel moteur JavaScript exécute votre code dans une app Expo, et quelle est sa particularité ?
Réponse
Hermes (créé par Meta pour le mobile). Particularité : le JS est compilé en bytecode au moment du build — l’app ne parse pas de source au lancement, d’où un démarrage rapide et une mémoire réduite.
2. Que remplace JSI, et quel était le défaut principal de l’ancien système ?
Réponse
JSI remplace le bridge : l’ancien mécanisme sérialisait chaque échange JS ↔ natif en JSON, de façon uniquement asynchrone et par lots — coûteux et saturable. JSI donne au JS des références C++ directes sur les objets natifs, sans sérialisation, avec appels synchrones possibles.
3. Quel composant de la New Architecture transforme votre arbre React en widgets, et qui calcule le layout ?
Réponse
Fabric (le renderer) projette l’arbre React en widgets natifs ; le layout flexbox est calculé par Yoga, une bibliothèque C++.
4. Où vit votre code applicatif dans l’APK final, et pourquoi est-ce important ?
Réponse
Dans le bundle JS (bytecode Hermes) produit par Metro, embarqué à côté du code natif. C’est important parce qu’un bundle peut être remplacé sans réinstallation : c’est le fondement des mises à jour OTA (EAS Update, Partie 12).
5. Un article de 2021 explique que RN est lent à cause de la sérialisation JSON. Que lui répondre ?
Réponse
C’est périmé : depuis la New Architecture (par défaut depuis RN 0.76, généralisée en 2026), il n’y a plus de bridge JSON — JSI fait des appels directs C++. Les benchmarks pré-2023 ne décrivent plus le React Native actuel.
👉 Chapitre suivant : 1.3 — Expo vs React Native « nu » — maintenant que vous savez ce qu’est RN, voyons pourquoi on ne l’utilise (presque) jamais seul.