Understanding Hermes, Fabric, and the New Architecture in React Native


If you’ve been building React Native apps for a while, chances are you’ve heard terms like Hermes, TurboModules, and Fabric floating around. When I recently upgraded from an older React Native project to v0.80.2, I realized these weren’t just buzzwords—they’re a fundamental shift in how React Native works under the hood.

This guide will demystify these technologies and show you why they matter for your next React Native project.



📋 Table of Contents



🎯 The Evolution of React Native

Before diving into the new technologies, let’s understand the journey:

📅 Timeline
2015: React Native Launch → JavaScript Bridge Architecture
2017: Hermes Development Begins → Focus on Mobile Performance
2018: New Architecture Announced → JSI Introduction
2022: New Architecture Stable → Fabric & TurboModules
2024: Default in New Projects → Mature Ecosystem
Enter fullscreen mode

Exit fullscreen mode



🧠 Hermes: The JavaScript Engine Built for Mobile

React Native originally relied on JavaScriptCore (JSC), but Hermes was introduced as a mobile-first JS engine optimized specifically for React Native apps.



Key Benefits:



🚀 Faster Startup Time

// Traditional JSC Flow
Source Code  Parse  Compile  Execute

// Hermes Flow
Source Code  Precompile to Bytecode  Execute
Enter fullscreen mode

Exit fullscreen mode



💾 Lower Memory Usage

Perfect for low-end Android devices. Here’s a real-world comparison:

Memory Usage Comparison (50MB App):
JSC:    ~185MB RAM
Hermes: ~136MB RAM (-26%)
Enter fullscreen mode

Exit fullscreen mode



🔄 Smaller Bundle Size

Bundle Size Impact:
Before Hermes: 41MB APK
After Hermes:  29MB APK (-29%)
Enter fullscreen mode

Exit fullscreen mode



💡 Enabling Hermes in Your Project

Most new React Native projects now enable Hermes by default. Here’s how to check:

Android (android/app/build.gradle):

android {
    ...
    packagingOptions {
        pickFirst '**/libc++_shared.so'
        pickFirst '**/libjsc.so'
    }
}

// Hermes is enabled by this flag
hermesEnabled = true
Enter fullscreen mode

Exit fullscreen mode

iOS (ios/Podfile):

use_react_native!(
  :path => config[:reactNativePath],
  # Hermes is now enabled by default
  :hermes_enabled => true,
  :fabric_enabled => flags[:fabric_enabled],
)
Enter fullscreen mode

Exit fullscreen mode



⚡ The New Architecture: Beyond the Bridge

The classic React Native model relied on a Bridge for JS-to-Native communication:



Old Bridge Architecture:

┌─────────────┐     JSON      ┌──────────────┐
│ JavaScript  │ ←----------→  │    Native    │
│   Thread    │   Serialize   │   Thread     │
└─────────────┘               └──────────────┘
       ↓                              ↓
   [Async Queue]                [Processing]
       ↓                              ↓
   [Batching]                    [Response]
Enter fullscreen mode

Exit fullscreen mode



New JSI Architecture:

┌─────────────┐               ┌──────────────┐
│ JavaScript  │ ←----------→  │    Native    │
│   Thread    │  Direct C++   │   Thread     │
└─────────────┘   Interface   └──────────────┘
       ↓                              ↓
   [Immediate]                  [Immediate]
Enter fullscreen mode

Exit fullscreen mode



Performance Impact:

// Old Bridge (Async)
NativeModules.Camera.takePicture((result) => {
  // Wait for bridge...
  console.log(result); // ~16-32ms delay
});

// New JSI (Sync when needed)
const result = Camera.takePictureSync();
console.log(result); // <1ms delay
Enter fullscreen mode

Exit fullscreen mode



🛠 TurboModules: Native Modules, Supercharged

TurboModules revolutionize how we interact with native code:



Key Features:

  • Lazy Loading: Modules load only when needed
  • Type Safety: Auto-generated TypeScript bindings
  • Synchronous Calls: When performance matters
  • Direct JSI Access: No serialization overhead



Creating a TurboModule:

1. Define the Native Module Interface:

// specs/NativeDeviceInfo.ts
import type {TurboModule} from 'react-native';
import {TurboModuleRegistry} from 'react-native';

export interface Spec extends TurboModule {
  getBatteryLevel(): number;
  getDeviceId(): string;
  isTablet(): boolean;
}

export default TurboModuleRegistry.getEnforcing<Spec>('DeviceInfo');
Enter fullscreen mode

Exit fullscreen mode

2. Native Implementation (iOS):

// RNDeviceInfo.mm
#import "RNDeviceInfo.h"

@implementation RNDeviceInfo

RCT_EXPORT_MODULE(DeviceInfo)

- (NSNumber *)getBatteryLevel {
  UIDevice *device = [UIDevice currentDevice];
  device.batteryMonitoringEnabled = YES;
  return @(device.batteryLevel);
}

- (NSString *)getDeviceId {
  return [[[UIDevice currentDevice] identifierForVendor] UUIDString];
}

- (NSNumber *)isTablet {
  return @(UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad);
}

@end
Enter fullscreen mode

Exit fullscreen mode

3. Usage in JavaScript:

import DeviceInfo from './specs/NativeDeviceInfo';

// Direct, synchronous calls!
const batteryLevel = DeviceInfo.getBatteryLevel();
const deviceId = DeviceInfo.getDeviceId();
const isTablet = DeviceInfo.isTablet();

console.log(`Battery: ${batteryLevel * 100}%`);
console.log(`Device ID: ${deviceId}`);
console.log(`Is Tablet: ${isTablet}`);
Enter fullscreen mode

Exit fullscreen mode



🎨 Fabric: Modern UI for Modern React

Fabric is React Native’s new rendering system, built from the ground up to support modern React features:



Architecture Comparison:

Old Renderer:

React Components
      ↓
Shadow Thread (Layout)
      ↓
Bridge (JSON)
      ↓
Main Thread (UI)
Enter fullscreen mode

Exit fullscreen mode

Fabric Renderer:

React Components
      ↓
Fabric C++ Core
   ↙     ↘
iOS UI   Android UI
(Sync)    (Sync)
Enter fullscreen mode

Exit fullscreen mode



Key Improvements:



1. Concurrent Rendering Support

// Now works seamlessly with React 18 features
function App() {
  return (
    <Suspense fallback={<LoadingSpinner />}>
      <ExpensiveComponent />
    Suspense>
  );
}
Enter fullscreen mode

Exit fullscreen mode



2. Priority-based Rendering

// High priority updates (user input)
<TextInput onChangeText={setText} />

// Low priority updates (background data)
<LargeList data={backgroundData} />
Enter fullscreen mode

Exit fullscreen mode



3. Better Animations

// Fabric enables smoother 60fps animations
const animatedValue = useSharedValue(0);

const animatedStyle = useAnimatedStyle(() => ({
  transform: [{
    translateX: withSpring(animatedValue.value * 100)
  }]
}));
Enter fullscreen mode

Exit fullscreen mode



📊 Performance Comparisons



Real-world Metrics:

┌─────────────────┬──────────┬──────────┬─────────┐
│ Metric          │ Old Arch │ New Arch │ Change  │
├─────────────────┼──────────┼──────────┼─────────┤
│ App Start Time  │ 3.2s     │ 1.8s     │ -44%    │
│ List Scroll FPS │ 47 fps   │ 59 fps   │ +25%    │
│ Memory Usage    │ 185 MB   │ 136 MB   │ -26%    │
│ Bundle Size     │ 41 MB    │ 29 MB    │ -29%    │
└─────────────────┴──────────┴──────────┴─────────┘
Enter fullscreen mode

Exit fullscreen mode



Benchmark Code:

// Measure startup performance
const startTime = Date.now();

AppRegistry.registerComponent(appName, () => App);

// Log after first render
const FirstRenderTracker = () => {
  useEffect(() => {
    console.log(`First render: ${Date.now() - startTime}ms`);
  }, []);
  return null;
};
Enter fullscreen mode

Exit fullscreen mode



🎯 Best Practices



1. Gradual Migration

// Start with non-critical modules
const MyModule = Platform.select({
  ios: NativeModules.MyModuleOld,
  android: TurboModuleRegistry.get<Spec>('MyModule'),
});
Enter fullscreen mode

Exit fullscreen mode



2. Type Safety First

// Always define TypeScript specs
interface Spec extends TurboModule {
  readonly constantsToExport: {
    readonly apiUrl: string;
    readonly version: string;
  };
  methodWithCallback(callback: (result: string) => void): void;
}
Enter fullscreen mode

Exit fullscreen mode



3. Performance Testing

// Use React DevTools Profiler
import {Profiler} from 'react';

<Profiler id="MyComponent" onRender={(id, phase, duration) => {
  console.log(`${id} (${phase}) took ${duration}ms`);
}}>
  <MyComponent />
</Profiler>
Enter fullscreen mode

Exit fullscreen mode



🚀 Conclusion

The new React Native architecture isn’t just an incremental update—it’s a fundamental reimagining of how JavaScript and native code communicate. With:

  • Hermes providing faster startup and lower memory usage
  • JSI eliminating the bridge bottleneck
  • TurboModules offering type-safe, lazy-loaded native modules
  • Fabric bringing modern React features to mobile

…your React Native apps can now rival truly native performance while maintaining the developer experience we love.



Source link

One thought on “Understanding Hermes, Fabric, and the New Architecture in React Native

Leave a Reply

Your email address will not be published. Required fields are marked *