NativeModules cũ:
- Register tất cả module ngay lúc app start → tốn memory/startup time dù chưa dùng.
- Method call gần như luôn async (Promise/callback) qua bridge; method đồng bộ phải khai báo riêng (isBlockingSynchronousMethod) và không được khuyến khích.
- API định nghĩa qua RCTBridgeModule (iOS Obj-C) / ReactContextBaseJavaModule (Android) — không type-safe, JS phải nhớ chính xác signature.
- Hệ quả: app có 100 module, dù dùng 10, vẫn pay cost startup cho 100.
TurboModules:
- Lazy load: chỉ load module khi gọi đến lần đầu (require('NativeFoo').foo() → load native binding tại runtime).
- Sync call qua JSI: getNumber() return number ngay, không Promise. (Async vẫn được khi cần I/O.)
- Type-safe: Codegen sinh code C++/Java/Obj-C từ TypeScript spec → JS gọi sai signature → compile error.
- Backward compat: API JS có thể giữ giống module cũ — migrate dần.
Spec file (TypeScript):
// NativeCalculator.ts
import { TurboModule, TurboModuleRegistry } from 'react-native'
export interface Spec extends TurboModule {
add(a: number, b: number): number
fetchUser(id: string): Promise<{ name: string; age: number }>
}
export default TurboModuleRegistry.getEnforcing<Spec>('Calculator')Codegen đọc spec → tự sinh:
- iOS: protocol NativeCalculatorSpec (Obj-C++).
- Android: abstract class NativeCalculatorSpec (Java).
Code native chỉ cần implement/extends NativeCalculatorSpec → signature hai phía luôn khớp.
Hiệu năng: lời gọi không serialize JSON, không qua queue, và app không trả chi phí khởi tạo cho module chưa dùng tới.
Lưu ý: từ RN 0.82 app chỉ chạy New Architecture; module viết theo kiểu cũ vẫn chạy nhờ interop layer, nhưng library mới nên viết theo Turbo Native Module. Gọi đồng bộ sẽ chặn JS thread — method có I/O nên trả Promise.