ספריית React Native עם מודול Native: ארכיטקטורה חדשה, JSI, TurboModules
פיתוח אפליקציית מובייל נתקל לעיתים קרובות ב-SDK קנייניים מספקים — אינטגרציה עם ביומטריה, מצלמות או מערכות MDM. ספריות מוכנות מ-React Native Community rarely מכסות מקרים אלה, ולכן יש צורך לכתוב מודול native מאפס. אנחנו עושים זאת כבר למעלה מ-5 שנים, ומסרנו יותר מ-10 פרויקטים עם מודולי native ל-iOS ו-Android. הניסיון שלנו מראה שבחירת הארכיטקטורה הנכונה מקצרת את זמן הפיתוח פי 2–3.
ארכיטקטורה ישנה לעומת ארכיטקטורה חדשה: הבדלים עיקריים
| פרמטר | ארכיטקטורה ישנה (Bridge) | ארכיטקטורה חדשה (TurboModules + JSI) |
|---|---|---|
| מנגנון קריאה | אסינכרוני, דרך סריאליזציית JSON | סינכרוני, קישור C++ ישיר |
| זמן השהיה | 1–5 אלפיות שנייה לכל קריאה | < 0.1 אלפית שנייה |
| טיפול ב-threads | thread ה-JS נחסם בקריאות סינכרוניות | thread ה-JS לא נחסם (מודל שונה) |
| תמיכה בגרסאות React Native | 0.68 ומטה | 0.73+ (מופעל כברירת מחדל) |
הארכיטקטורה החדשה משתמשת ב-JSI (JavaScript Interface) — קישור C++ ישיר בין מנוע ה-JS (Hermes) לקוד native. TurboModules נטענים באופן עצלני ומופעלים באופן סינכרוני. עבור פעולות בתדירות גבוהה (כל פריים של אנימציה, עיבוד שמע בזמן אמת), זה קריטי: הפרש הביצועים מגיע לפי 5–10. הספרייה חייבת לתמוך בשני הווריאנטים דרך מפרט codegen.
למה הארכיטקטורה החדשה מהירה יותר
ה-Bridge הישן עובד אסינכרונית דרך סריאליזציית JSON. קריאה למתודת native עוברת: JavaScript → סריאליזציית JSON → תור Bridge → דה-סריאליזציה → Java/ObjC. זה מוסיף כ-1–5 אלפיות שנייה לכל קריאה והופך גישה סינכרונית לקוד native לבלתי אפשרית. הארכיטקטורה החדשה משתמשת ב-JSI (JavaScript Interface) — קישור C++ ישיר בין מנוע ה-JS (Hermes) לקוד native. TurboModules נטענים באופן עצלני ומופעלים באופן סינכרוני. עבור פעולות בתדירות גבוהה (כל פריים של אנימציה, עיבוד שמע בזמן אמת), זה קריטי.
React Native 0.73+ כולל את הארכיטקטורה החדשה כברירת מחדל. הספרייה חייבת לתמוך בשני הווריאנטים דרך מפרט codegen.
איך ליצור ספרייה דרך create-react-native-library
npx create-react-native-library@latest my-module — scaffold סטנדרטי. יוצר מבנה:
my-module/
android/src/main/java/…/MyModule.kt
ios/MyModule.mm (Objective-C++ для JSI bridge)
src/index.tsx — TypeScript API
src/NativeMyModule.ts — codegen spec מפרט Codegen
קובץ ה-TypeScript מתאר את החוזה שממנו codegen מייצר קוד דבק C++:
// NativeMyModule.ts
import type { TurboModule } from 'react-native';
import { TurboModuleRegistry } from 'react-native';
export interface Spec extends TurboModule {
multiply(a: number, b: number): Promise<number>;
getDeviceId(): string; // синхронный метод — только в New Architecture
}
export default TurboModuleRegistry.getEnforcing<Spec>('MyModule');
my-module/ android/src/main/java/…/MyModule.kt ios/MyModule.mm (Objective-C++ для JSI bridge) src/index.tsx — TypeScript API src/NativeMyModule.ts — codegen spec זורק שגיאה בעת ההפעלה אם המודול native לא רשום — טוב יותר מאשר undefined שקט.
יישום Android: Kotlin + ReactPackage
class MyModule(reactContext: ReactApplicationContext) : NativeMyModuleSpec(reactContext) {
override fun getName() = NAME
override fun multiply(a: Double, b: Double): Promise<Double> {
return Promise.resolve(a * b)
}
override fun getDeviceId(): String {
return Settings.Secure.getString(
reactApplicationContext.contentResolver,
Settings.Secure.ANDROID_ID
)
}
companion object {
const val NAME = "MyModule"
}
}// NativeMyModule.ts import type { TurboModule } from 'react-native'; import { TurboModuleRegistry } from 'react-native'; export interface Spec extends TurboModule { multiply(a: number, b: number): Promise<number>; getDeviceId(): string; // синхронный метод — только в New Architecture } export default TurboModuleRegistry.getEnforcing<Spec>('MyModule'); הוא מחלקה אבסטרקטית שנוצרת על ידי codegen ממפרט ה-TypeScript. אם מתודה לא מיושמת — שגיאת קומפילציה, לא קריסת ריצה. זה יתרון מרכזי של הארכיטקטורה החדשה.
getEnforcing רושם את המודול:
class MyPackage : ReactPackage {
override fun createNativeModules(context: ReactApplicationContext) = listOf(MyModule(context))
override fun createViewManagers(context: ReactApplicationContext) = emptyList<ViewManager<*, *>>()
} iOS: גשר Objective-C++
עבור הארכיטקטורה החדשה, יישום ה-iOS נכתב ב-Objective-C++ (class MyModule(reactContext: ReactApplicationContext) : NativeMyModuleSpec(reactContext) { override fun getName() = NAME override fun multiply(a: Double, b: Double): Promise<Double> { return Promise.resolve(a * b) } override fun getDeviceId(): String { return Settings.Secure.getString( reactApplicationContext.contentResolver, Settings.Secure.ANDROID_ID ) } companion object { const val NAME = "MyModule" } } ) או Swift עם wrapper של ObjC. Swift לא תומך ב-JSI באופן טבעי ללא גשר, ולכן קובץ NativeMyModuleSpec עם ReactPackage נשאר חובה.
// MyModule.mm
#import "MyModule.h"
#import <React/RCTUtils.h>
@implementation MyModule
RCT_EXPORT_MODULE()
- (NSString *)getDeviceId {
return [[[UIDevice currentDevice] identifierForVendor] UUIDString];
}
@end
עבור מתודות סינכרוניות בארכיטקטורה הישנה: class MyPackage : ReactPackage { override fun createNativeModules(context: ReactApplicationContext) = listOf(MyModule(context)) override fun createViewManagers(context: ReactApplicationContext) = emptyList<ViewManager<*, *>>() } — זה עובד אבל חוסם את thread ה-JS. בארכיטקטורה החדשה, סינכרוניות דרך JSI לא חוסמת את thread ה-JS — מודל שונה מהותית.
רכיבי View Native
אם המשימה דורשת View native מותאם אישית (למשל, מפות SDK, נגן וידאו מותאם), אנו משתמשים ב-.mm ב-Android / .mm ב-iOS. הארכיטקטורה החדשה מציגה #import <React/RCTUtils.h> עבור רכיבים native — אנלוגי ל-TurboModules עבור תצוגות. Codegen מייצר // MyModule.mm #import "MyModule.h" #import <React/RCTUtils.h> @implementation MyModule RCT_EXPORT_MODULE() - (NSString *)getDeviceId { return [[[UIDevice currentDevice] identifierForVendor] UUIDString]; } @end ממפרט TypeScript עם RCT_EXPORT_BLOCKING_SYNCHRONOUS_METHOD.
תמיכה ב-Expo
אם האפליקציה משתמשת ב-Expo managed workflow, המודול native דורש את Expo Modules API במקום React Native חשוף. ViewManager יוצר את ה-scaffold הנכון. RCTViewManager נרשם אוטומטית ללא Fabric — Expo Autolinking מוצא את המודול דרך ComponentDescriptor.
שגיאות אופייניות
מודול לא נמצא בזמן ריצה
שכחתם להריץ `pod install` ב-iOS לאחר הוספת המודול.סוגים לא תואמים
מפרט ה-TypeScript אומר `number`, Kotlin מקבל `Double` (בסדר), Swift מקבל `Int` (קריסה). כל המספרים ב-JS הם `Double` בצד ה-native.הפרת thread ראשי
קריאה לקוד UI ממתודת native ללא שליחה ל-thread הראשי: `DispatchQueue.main.async` / `UiThreadUtil.runOnUiThread`.מה כלול בפיתוח מודול Native Turnkey
המהנדסים שלנו (5+ שנות ניסיון ב-React Native) מספקים:
- ניתוח דרישות ועיצוב API של המודול
- יישום קוד native ב-Kotlin ו-Objective-C++/Swift
- יצירת קוד ממפרט TypeScript ואינטגרציה עם הארכיטקטורה החדשה
- בדיקות יחידה ואינטגרציה לשתי הפלטפורמות
- בנייה ופרסום ל-npm/Expo registry
- תיעוד המודול ודוגמאות שימוש
- תמיכה לאחר השחרור (תיקוני באגים, עדכונים לגרסאות RN חדשות)
לוחות זמנים משוערים
| סוג מודול | לוח זמנים |
|---|---|
| פשוט (1–3 מתודות) | 3 עד 5 ימים |
| מורכב (EventEmitter, View, שתי הארכיטקטורות) | 3 עד 5 שבועות |
העלות מחושבת באופן אישי. אנו נעריך את הפרויקט שלכם — צרו קשר לייעוץ.
איך אנחנו מבטיחים איכות
שימוש ב-codegen מבטל שגיאות קומפילציה בזמן ריצה. כל מודול נבדק על מכשירים אמיתיים (iOS 15+ ו-Android 10+). אנו מספקים תעודת תאימות עם גרסאות React Native העדכניות. אנו מבטיחים תמיכה חינמית ל-30 יום לאחר המסירה.
לפי התיעוד הרשמי של React Native, JSI מפחית את זמן ההשהיה לכל קריאה מ-1–5 אלפיות שנייה ל-<0.1 אלפית שנייה.
הזמינו פיתוח מודול native — קבלו ייעוץ מהמהנדסים שלנו.







