0Pricing
React Native Academy · درس

وحدات Turbo الأصلية باستخدام JSI

عرّفوا ملف مواصفات TypeScript لوحدة Turbo أصلية، ونفّذوها في Kotlin وSwift باستخدام الواجهة المنشأة عبر codegen، واستدعوا الوحدة بشكل متزامن عبر JSI.

وحدات Turbo الأصلية باستخدام JSI درس مجاني في React Native Academy على CoddyKit. هذا هو الدرس 3 من أصل 4. يمكنك قراءة الدرس كاملاً أدناه مجاناً — ثم تمرن عليه مباشرة في المتصفح باستخدام محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7. هذا الدرس جزء من مسار التعلم في React Native Academy، وتقدمك يتزامن عبر الويب وتطبيق CoddyKit. تتضمن دورة React Native Academy 4 دروس في المجموع.

بعض أجزاء هذا الدرس لم تُترجم بعد وتظهر باللغة الإنجليزية.

The Problem with the Legacy Bridge

The legacy React Native bridge serializes every message between JavaScript and native into JSON, then deserializes it on the other side. This round-trip adds latency for every native call and blocks threads while serialization happens. For frequent calls like scroll events or animations, this overhead causes frame drops. JSI (JavaScript Interface) was created to eliminate this bottleneck.

What Is JSI

JSI (JavaScript Interface) is a lightweight C++ layer that lets JavaScript hold direct references to C++ host objects. Instead of sending a JSON-serialized message across the bridge, a JS call invokes a C++ function pointer directly and synchronously. This means native calls can be synchronous, zero-copy, and orders of magnitude faster than bridge-based calls.

Turbo Modules Architecture Overview

Turbo Native Modules are the new module system built on JSI. Key differences from legacy modules include: lazy loading (modules initialize only when first accessed instead of all at startup), typed interfaces (generated from a TypeScript spec so types are guaranteed on both sides), and synchronous calls possible without blocking the JS thread via JSI. The codegen tool generates the boilerplate C++ and native glue code automatically.

Writing the TypeScript Spec File

A Turbo Module starts with a TypeScript spec file that declares the module's interface. This file lives in your project and is processed by react-native-codegen to generate native interface files. The spec must import TurboModuleRegistry and define a type that extends TurboModule.

// NativeDeviceInfo.ts (spec file)
import type { TurboModule } from 'react-native';
import { TurboModuleRegistry } from 'react-native';

export interface Spec extends TurboModule {
  getDeviceModel(): string;
  getBatteryLevel(): Promise<number>;
  addListener(eventType: string): void;
  removeListeners(count: number): void;
}

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

Running Codegen to Generate Native Code

After writing the TypeScript spec, you run React Native Codegen to generate the native interface files. For managed Expo projects, this happens automatically during expo prebuild. For bare React Native projects, run yarn react-native codegen. Codegen outputs Swift/Kotlin interfaces and C++ glue code in the build/generated folder that your native implementation must conform to.

# Bare React Native — run codegen manually
cd android && ./gradlew generateCodegenArtifactsFromSchema

# Then check generated files
ls android/app/build/generated/source/codegen/jni/
# NativeDeviceInfoJSI-generated.cpp
# NativeDeviceInfoJSI.h

Implementing the Module in Kotlin

The Kotlin implementation must extend the codegen-generated abstract class (e.g., NativeDeviceInfoSpec) and override each method declared in the spec. Because the signatures are generated from TypeScript, there is no type mismatch between JS and native — the codegen enforces them at build time rather than at runtime.

// DeviceInfoModule.kt
package com.yourapp

import com.facebook.react.bridge.ReactApplicationContext
import com.yourapp.NativeDeviceInfoSpec

class DeviceInfoModule(context: ReactApplicationContext) :
    NativeDeviceInfoSpec(context) {

    companion object {
        const val NAME = 'DeviceInfo'
    }

    override fun getName(): String = NAME

    override fun getDeviceModel(): String {
        return android.os.Build.MODEL
    }
}

Implementing the Module in Swift

The Swift implementation conforms to the codegen-generated protocol (e.g., NativeDeviceInfoSpec). Unlike legacy modules, there is no separate bridge .m file needed for Turbo Modules — the JSI layer handles the binding automatically once the module is registered. The protocol guarantees that the Swift method signatures match the TypeScript spec exactly.

// DeviceInfoModule.swift
import Foundation

@objc(DeviceInfoModule)
class DeviceInfoModule: NSObject, NativeDeviceInfoSpec {

  func getDeviceModel() -> String {
    return UIDevice.current.model
  }

  func getBatteryLevel(
    _ resolve: @escaping RCTPromiseResolveBlock,
    reject: @escaping RCTPromiseRejectBlock
  ) {
    UIDevice.current.isBatteryMonitoringEnabled = true
    resolve(UIDevice.current.batteryLevel * 100)
  }
}

Synchronous Calls via JSI

One of the biggest JSI benefits is the ability to call native synchronously from JS. When a Turbo Module method returns a non-Promise type (like string or number in the spec), JSI can return the value immediately without scheduling an async callback. This unlocks patterns like reading cached values synchronously that were impossible with the legacy bridge.

// TypeScript spec — synchronous return type
export interface Spec extends TurboModule {
  getDeviceModel(): string;  // synchronous
  getBatteryLevel(): Promise<number>;  // still async
}

// Usage in JS — getDeviceModel() is synchronous
import NativeDeviceInfo from './NativeDeviceInfo';

const model = NativeDeviceInfo.getDeviceModel(); // no await needed
console.log('Model:', model);

Enabling the New Architecture

Turbo Modules require the New Architecture to be enabled in your project. For Android, set newArchEnabled=true in android/gradle.properties. For iOS, set RCT_NEW_ARCH_ENABLED=1 in the Podfile and run pod install. Expo SDK 50+ enables the new architecture automatically for managed workflow projects using the latest config.

# android/gradle.properties
newArchEnabled=true

# ios/Podfile — add before use_react_native!
ENV['RCT_NEW_ARCH_ENABLED'] = '1'

# Then reinstall pods
cd ios && pod install

Registering a Turbo Module

Turbo Modules are registered via a TurboModuleManagerDelegate instead of a ReactPackage. On Android you modify MainApplicationTurboModuleManagerDelegate.kt; on iOS you modify RCTAppDelegate.mm. The codegen also generates a ModuleProvider that wires up the module automatically when you follow the standard naming conventions.

// Android: MainApplicationTurboModuleManagerDelegate.kt
override fun getModule(
    reactApplicationContext: ReactApplicationContext,
    name: String
): NativeModule? {
    return when (name) {
        DeviceInfoModule.NAME -> DeviceInfoModule(reactApplicationContext)
        else -> null
    }
}

Comparing Legacy vs Turbo Module Performance

Benchmarks show Turbo Modules can be 2–3x faster for high-frequency calls compared to legacy bridge modules. The improvement is most noticeable for calls made in rapid succession — such as gesture handlers or animation drivers. For infrequent calls like camera setup, the difference is negligible. Migrate to Turbo Modules when performance-critical native code needs to keep up with 60fps interactions.

// Performance benchmark pattern
const ITERATIONS = 10000;
const start = Date.now();

for (let i = 0; i < ITERATIONS; i++) {
  // Synchronous JSI call
  const model = NativeDeviceInfo.getDeviceModel();
}

const elapsed = Date.now() - start;
console.log('10k JSI calls in', elapsed, 'ms');
// Turbo: ~8ms  vs  Legacy bridge: ~80ms

Quick Check

Test your understanding of React Native Mobile Development concepts from this lesson.

Lesson Recap

In this lesson you learned: how JSI eliminates JSON serialization overhead from the legacy bridge, how to write a TypeScript spec file that codegen uses to generate native interfaces, and how to implement the generated spec in both Kotlin and Swift. You also saw how to enable the New Architecture and the performance benefits of synchronous JSI calls. Next up we explore async callbacks, promises, and native events.

الأسئلة الشائعة

هل درس «وحدات Turbo الأصلية باستخدام JSI» مجاني؟

نعم — نص درس «وحدات Turbo الأصلية باستخدام JSI» كامل متاح مجاناً هنا على الويب. لتمرينه بشكل تفاعلي (محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7) وفتح باقي دورة React Native Academy، انتقل إلى CoddyKit PRO. تتضمن دورة React Native Academy 4 دروس في المجموع.

ماذا ستتعلم في «وحدات Turbo الأصلية باستخدام JSI»؟

عرّفوا ملف مواصفات TypeScript لوحدة Turbo أصلية، ونفّذوها في Kotlin وSwift باستخدام الواجهة المنشأة عبر codegen، واستدعوا الوحدة بشكل متزامن عبر JSI. تتمرن على React Native Academy مع أكواد عملية تشغلها مباشرة في المتصفح، ومدرس ذكاء اصطناعي متاح 24/7 يجيب على أسئلتك أثناء عملك.

هل أحتاج إلى خبرة سابقة لأبدأ React Native Academy؟

لا تُشترط خبرة سابقة. React Native Academy على CoddyKit منظم للمبتدئين حتى المتقدمين، لذا يمكنك البدء من هنا أو من البداية والتقدم بسرعتك الخاصة. هذا هو الدرس 3 من أصل 4.

كم من الوقت يستغرق درس «وحدات Turbo الأصلية باستخدام JSI»؟

معظم دروس CoddyKit تستغرق حوالي 5–10 دقائق. كل منها موجز وتفاعلي، لذا تحرز تقدماً مستمراً وتستأنف من حيث توقفت عبر الويب والتطبيق.

هل يمكنني كتابة وتشغيل أكواد في درس React Native Academy هذا؟

نعم. كل درس في React Native Academy يتضمن محرر أكواد مدمج، لذا تكتب وتشغل أكواداً حقيقية مباشرة في متصفحك وتحصل على تعليقات فورية من الذكاء الاصطناعي — بدون إعداد محلي.

جميع الدروس في هذه الدورة

  1. كتابة وحدة أصلية قديمة باستخدام Kotlin
  2. كتابة وحدة أصلية قديمة باستخدام Swift
  3. وحدات Turbo الأصلية باستخدام JSI
  4. ردود الاستدعاء والوعود والأحداث غير المتزامنة من الشيفرة الأصلية
← العودة إلى React Native Academy