Cách hoạt động: JS thread và Native thread giao tiếp qua Bridge — 1 async message queue. Mọi data phải JSON serialize/deserialize khi qua Bridge.
Data flow:
JS Thread Bridge Native Thread
| | |
|-- JSON.stringify(msg) --> | |
| |-- JSON.parse(msg) ------>|
| | |
| |<-- JSON.stringify(res) --|
|<-- JSON.parse(res) ----- | |
Bottlenecks:
Thay thế Bridge bằng gì? JSI tạo C++ host objects mà JS có thể gọi trực tiếp, synchronously. Không serialization. Không async queue.
Cơ chế: JSI expose C++ objects vào JS runtime (Hermes). JS gọi method trên object đó → thực thi C++ code trực tiếp, không qua Bridge.
// Old Bridge: async, serialized
NativeModules.BatteryModule.getBatteryLevel()
.then(level => console.log(level));
// New JSI: synchronous, direct
const level = global.__turboModuleProxy.BatteryModule.getBatteryLevel();
Tại sao game-changer:
Thay thế NativeModules cũ.
| Old NativeModules | TurboModules | |
|---|---|---|
| Loading | Eager (tất cả load khi app start) | Lazy (load khi lần đầu sử dụng) |
| Communication | Bridge (async, serialized) | JSI (sync, direct) |
| Type safety | Không (runtime errors) | Có (Codegen từ JS/TS specs) |
| Startup impact | Cao (load tất cả) | Thấp (lazy) |
Thay thế old UI Manager. Fabric = new rendering system dựa trên JSI.
Auto-generate native interfaces (Java/ObjC/C++) từ JavaScript/TypeScript type specifications. Đảm bảo type safety giữa JS và native code tại build time.
// JS Spec file: NativeBatteryModule.ts
import type { TurboModule } from 'react-native';
import { TurboModuleRegistry } from 'react-native';
export interface Spec extends TurboModule {
getBatteryLevel(): number;
isCharging(): boolean;
}
export default TurboModuleRegistry.getEnforcing<Spec>('BatteryModule');
Codegen sẽ generate native interface code từ spec này → compile-time errors nếu native implementation không match.
class BatteryModule(reactContext: ReactApplicationContext) :
ReactContextBaseJavaModule(reactContext) {
override fun getName() = "BatteryModule"
@ReactMethod
fun getBatteryLevel(promise: Promise) {
val batteryManager = reactApplicationContext
.getSystemService(Context.BATTERY_SERVICE) as BatteryManager
val level = batteryManager
.getIntProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY)
promise.resolve(level)
}
}
@objc(BatteryModule)
class BatteryModule: NSObject {
@objc func getBatteryLevel(
_ resolve: @escaping RCTPromiseResolveBlock,
rejecter reject: @escaping RCTPromiseRejectBlock
) {
UIDevice.current.isBatteryMonitoringEnabled = true
let level = UIDevice.current.batteryLevel
resolve(Int(level * 100))
}
@objc static func requiresMainQueueSetup() -> Bool {
return false
}
}
Send events từ native → JS (push-based, không phải request-response).
import { NativeEventEmitter, NativeModules } from 'react-native';
const emitter = new NativeEventEmitter(NativeModules.BatteryModule);
useEffect(() => {
const subscription = emitter.addListener('BatteryChanged', (event) => {
setBatteryLevel(event.level);
});
return () => subscription.remove();
}, []);
// BatteryModule.ts
export type BatteryStatus = {
level: number;
isCharging: boolean;
};
export interface BatteryModuleApi {
getStatus(): Promise<BatteryStatus>;
startObserving(): void;
stopObserving(): void;
}
// Component chỉ phụ thuộc contract này, không phụ thuộc Android/iOS detail.
Tip: Trước khi viết Kotlin/Swift, chốt API JS/TS trước: method nào async, event nào push lên JS, lỗi trả về format gì, permission được xử lý ở đâu.
Bridge problems: Async-only communication, JSON serialization/deserialization overhead, single-threaded queue, eager module loading.
New Architecture fixes: JSI cho synchronous calls không serialization. TurboModules cho lazy loading. Fabric cho concurrent rendering + sync layout. Codegen cho type safety.
JSI = C++ interface cho phép JS gọi native functions trực tiếp, synchronously, không serialization. Bridge = async message queue với JSON serialization. JSI nhanh hơn orders of magnitude vì không có serialization overhead và direct memory access.
TurboModules: lazy loading (load khi dùng), JSI-based (sync), type-safe (Codegen). Old NativeModules: eager loading (tất cả load khi start), Bridge-based (async), no type safety. TurboModules cải thiện startup time + runtime performance đáng kể.
Fabric cho phép synchronous layout measurement (trước đây phải async → layout flicker), concurrent rendering (React 18 features), priority-based rendering (user input trước data fetch), shared C++ Yoga engine giữa JS và native.
Auto-generate native interface code (Java/ObjC/C++) từ TypeScript specs. Đảm bảo JS ↔ Native contract type-safe tại build time thay vì runtime crashes. Developer viết TS spec → Codegen generate native boilerplate.
Khi cần: platform-specific SDK (payment gateways), hardware APIs (Bluetooth, NFC, biometrics), CPU-intensive tasks (image processing), hoặc khi không có community library phù hợp. Luôn check xem có library sẵn trước khi viết native module.
Case: App tích hợp SDK thanh toán native. Android trả lỗi dạng code/message, iOS throw string. JS layer phải xử lý nhiều nhánh và bug khó test.
Cách xử lý: Chuẩn hóa error ở native boundary thành { code, message, recoverable }. Viết adapter JS và test mock module trước khi nối SDK thật.
Native module tốt bắt đầu từ contract JS rõ ràng. Kotlin/Swift chỉ là implementation detail phía sau contract đó.