Skip to content

t1k:rn:performance:native-modules

FieldValue
Moduleperformance
Version1.6.3
Effortmedium
Tools

Keywords: bridge, fabric, JSI, native modules, react native, turbo modules

/t1k:rn:performance:native-modules

Old: JS → Bridge (serialized JSON) → Native
New: JS → JSI (direct C++ binding) → Native (synchronous)

New Architecture = Turbo Modules (TurboModule API) + Fabric (new renderer). Enabled by default in RN 0.74+.

// specs/NativeMyModule.ts — CodeGen spec
import type { TurboModule } from 'react-native';
import { TurboModuleRegistry } from 'react-native';
export interface Spec extends TurboModule {
multiply(a: number, b: number): Promise<number>;
getDeviceName(): string; // synchronous via JSI
}
export default TurboModuleRegistry.getEnforcing<Spec>('MyModule');
// android — MyModuleModule.kt
class MyModuleModule(reactContext: ReactApplicationContext) : NativeMyModuleSpec(reactContext) {
override fun multiply(a: Double, b: Double, promise: Promise) {
promise.resolve(a * b)
}
override fun getName() = NAME
companion object { const val NAME = "MyModule" }
}

Expo Modules API (Preferred — wraps Turbo Modules)

Section titled “Expo Modules API (Preferred — wraps Turbo Modules)”
modules/my-module/src/MyModuleModule.ts
import { requireNativeModule } from 'expo-modules-core';
const MyModule = requireNativeModule('MyModule');
export default MyModule;

Expo Modules API auto-generates CodeGen specs — no manual spec file needed.

// Only use JSI for performance-critical synchronous operations
// MMKV, Reanimated, and Gesture Handler use JSI internally
// For most cases, async Turbo Modules are sufficient
// Even faster than Turbo Modules — uses C++ templates
// Use for compute-intensive work: image processing, crypto, ML
  • Prefer Expo Modules API over raw Turbo Module spec for new modules
  • Async by default — only use synchronous JSI for truly sync-critical paths (e.g., storage reads)
  • CodeGen spec types must match exactly — number in TS = Double in Kotlin/Swift
  • Test native modules with eas build --profile development — not Expo Go
  • Old Architecture NativeModules still work in New Architecture via compatibility layer — migration is not urgent
  • JSI modules crash if accessed before JS runtime is ready — guard with global.__turboModuleProxy
  • requireNativeModule throws if module not linked — wrap in try/catch for optional modules
  • Android minSdk must be 24+ for New Architecture