Hermes Engine & Yoga Layout

📖 Concept

Hermes is Meta's JavaScript engine optimized specifically for React Native. It replaced JavaScriptCore (JSC) as the default engine and provides significant improvements in startup time, memory usage, and runtime performance.

Hermes key features:

  1. Ahead-of-Time (AOT) bytecode compilation: JS is compiled to bytecode at BUILD time, not at runtime. The app ships bytecode instead of JS text files.
  2. Reduced startup time: No parsing/compiling JS at launch — bytecode loads directly. Typical improvement: 30-50% faster start.
  3. Lower memory footprint: Optimized garbage collector, smaller runtime, no JIT compiler (intentionally — JIT uses more memory).
  4. Incremental GC: Short pauses instead of long stop-the-world GC cycles. Critical for 60fps rendering.
  5. ES6+ support: Proxies, async/await, Intl, WeakRef, FinalizationRegistry — most modern JS features.

Hermes limitations to know:

  • No JIT compilation — pure interpreter + AOT bytecode. Computation-heavy loops are slower than V8/JSC with JIT.
  • eval() is limited — dynamic code evaluation doesn't benefit from AOT.
  • Some Intl features are behind flags or limited.
  • Debugging uses Chrome DevTools Protocol (different from Safari for JSC).

Yoga Layout Engine: Yoga is Meta's cross-platform layout engine that implements a subset of CSS Flexbox. Every React Native component's layout is computed by Yoga.

Yoga key behaviors:

  • Default flexDirection is column (not row like web CSS)
  • Default alignItems is stretch
  • All dimensions are unitless (density-independent pixels)
  • Percentage values are relative to the parent's equivalent dimension
  • Yoga runs on the Shadow thread (old arch) or any thread (new arch)
  • Absolute positioning uses position: 'absolute' with top/left/right/bottom

Layout performance considerations:

  • Deep view hierarchies slow down Yoga calculations — flatten where possible
  • Frequent layout recalculations (dynamic content, keyboard) trigger Yoga repeatedly
  • onLayout callbacks fire on the JS thread after Yoga completes — can cause additional re-renders

💻 Code Example

codeTap to expand ⛶
1// === HERMES OPTIMIZATION TECHNIQUES ===
2
3// 1. Check if Hermes is running
4const isHermes = () => !!global.HermesInternal;
5console.log('Using Hermes:', isHermes());
6
7// 2. Hermes bytecode compilation
8// In metro.config.js, Hermes automatically compiles your JS:
9// source.js → compiled.hbc (Hermes Bytecode)
10// The .hbc file is what ships in the APK/IPA
11
12// 3. Profile-Guided Optimization
13// Hermes supports basic profile-guided compilation
14// Record hot functions → optimize their bytecode
15// This is configured in the build system, not in code
16
17// 4. Memory optimization with Hermes GC
18// Hermes uses a moving GC — objects can be relocated in memory
19// This means: DO NOT hold native pointers to JS objects
20// Use the new architecture (JSI) for proper C++ ↔ JS references
21
22// === YOGA LAYOUT DEEP DIVE ===
23
24// 5. Flexbox differences from web CSS
25import { View, StyleSheet } from 'react-native';
26
27const styles = StyleSheet.create({
28 // RN default: flexDirection: 'column' (web default: 'row')
29 container: {
30 flex: 1,
31 // These are RN-specific defaults different from web:
32 // flexDirection: 'column' (web: 'row')
33 // alignItems: 'stretch' (web: 'stretch' — same)
34 // flexShrink: 0 (web: 1)
35 },
36
37 // Absolute positioning — same concept, simpler API
38 overlay: {
39 position: 'absolute',
40 top: 0, left: 0, right: 0, bottom: 0,
41 // No z-index needed usually — later in source = higher
42 },
43
44 // Percentage sizes
45 halfWidth: {
46 width: '50%', // 50% of parent's width
47 height: '100%', // 100% of parent's height
48 },
49});
50
51// 6. Layout performance: FLAT vs NESTED
52// ❌ Deep nesting — Yoga must calculate more nodes
53const DeepNested = () => (
54 <View style={styles.wrapper}>
55 <View style={styles.outer}>
56 <View style={styles.middle}>
57 <View style={styles.inner}>
58 <Text>Content</Text>
59 </View>
60 </View>
61 </View>
62 </View>
63);
64
65// ✅ Flattened — fewer Yoga calculations
66const Flattened = () => (
67 <View style={styles.container}>
68 <Text style={styles.content}>Content</Text>
69 </View>
70);
71
72// 7. Avoiding layout thrashing
73// ❌ Reading layout then immediately causing re-layout
74const BadPattern = () => {
75 const [height, setHeight] = useState(0);
76
77 return (
78 <View
79 onLayout={(e) => {
80 // This fires → sets state → re-render → new layout → repeat
81 setHeight(e.nativeEvent.layout.height);
82 }}
83 style={{ minHeight: height + 50 }} // Depends on height — layout loop!
84 >
85 <Text>Content</Text>
86 </View>
87 );
88};
89
90// ✅ Use onLayout for reading, not for creating dependency loops
91const GoodPattern = () => {
92 const [height, setHeight] = useState(0);
93
94 return (
95 <>
96 <View onLayout={(e) => setHeight(e.nativeEvent.layout.height)}>
97 <Text>Measured Content</Text>
98 </View>
99 {/* Height used by DIFFERENT component — no loop */}
100 <View style={{ height: height + 50 }}>
101 <Text>Sized based on above</Text>
102 </View>
103 </>
104 );
105};

🏋️ Practice Exercise

Hermes & Yoga Exercises:

  1. Profile your app's startup time with and without Hermes (if you can test both engines)
  2. Use global.HermesInternal?.getRuntimeProperties() to inspect Hermes runtime details
  3. Create a deep view hierarchy (10+ levels) and measure layout time using the Performance monitor
  4. Flatten a complex nested layout and compare Yoga computation time
  5. Implement a responsive layout using Yoga's percentage and flex properties that adapts to different screen sizes
  6. Create a layout that triggers a layout loop (onLayout → setState → re-render) and then fix it

⚠️ Common Mistakes

  • Assuming Hermes has JIT like V8 — Hermes intentionally omits JIT to save memory and startup time; heavy math loops will be slower

  • Using eval() or dynamic code loading with Hermes — bytecode is compiled at build time, dynamic code can't benefit from AOT

  • Not knowing that RN's flexDirection defaults to 'column' — coming from web CSS where default is 'row' causes layout confusion

  • Creating deeply nested view hierarchies — each nested View adds a Yoga node that must be calculated; flatten when possible

  • Using onLayout to create circular layout dependencies — measuring → setting state → re-layout → measuring again = infinite loop

💼 Interview Questions

🎤 Mock Interview

Mock interview is powered by AI for Hermes Engine & Yoga Layout. Login to unlock this feature.