Bridge trong React Native — nó là gì, nguyên lý hoạt động và tương tác

Tác giả: IT Sectr Đã đăng: 2026-06-03 Thời gian đọc: 9 phút

Bridge là một thành phần kiến trúc của React Native cung cấp giao tiếp bất đồng bộ giữa luồng JavaScript và môi trường native của iOS và Android. Nó truyền các thông điệp JSON được tuần tự hóa qua hàng đợi, cho phép gọi các API native từ mã JS. Theo Meta, 2024, Bridge vẫn là nền tảng của các ứng dụng hiện có, mặc dù nó thua kém về hiệu suất so với kiến trúc mới trên JSI.

Điểm chính

  • Bridge là kênh giao tiếp bất đồng bộ giữa JavaScript và mã native trong React Native.
  • Tuần tự hóa — tất cả dữ liệu được chuyển đổi thành JSON trước khi truyền, tạo ra chi phí bổ sung.
  • Tính bất đồng bộ — các thông điệp được truyền qua hàng đợi, do đó JS không chặn luồng native.
  • Hạn chế — Bridge không phù hợp cho các lời gọi nhỏ thường xuyên do chi phí tuần tự hóa.
  • Thay thế — trong kiến trúc React Native mới, Bridge được thay thế bằng JSI và Turbo Module.

Bridge trong React Native là gì?

Bridge là một yếu tố kiến trúc quan trọng của React Native cung cấp giao tiếp bất đồng bộ hai chiều giữa luồng JavaScript, nơi logic nghiệp vụ của ứng dụng được thực thi, và các luồng native iOS và Android. Kể từ khi React Native ra mắt vào năm 2015, Bridge là cách duy nhất để mã JS tương tác với các API nền tảng — máy ảnh, định vị, hệ thống tệp, thông báo và các khả năng native khác.

Kiến trúc Bridge dựa trên nguyên lý hàng đợi thông điệp (message queue). Khi mã JavaScript gọi một phương thức native, yêu cầu được tuần tự hóa thành chuỗi JSON, được đặt vào hàng đợi và gửi bất đồng bộ sang phía native. Mã native xử lý yêu cầu, thực hiện thao tác tương ứng và gửi kết quả trở lại qua cùng hàng đợi đến luồng JS. Theo báo cáo của Meta tại React Conf 2021, có đến 10.000 thông điệp mỗi giây đi qua Bridge trong một ứng dụng trung bình.

Các luồng chính tham gia vào hoạt động của Bridge: JavaScript Thread (thực thi mã JS), Native Thread (thực thi thao tác native) và Shadow Thread (tính toán bố cục bằng Yoga). Mỗi luồng hoạt động độc lập, đảm bảo tính phản hồi của UI — các hoạt ảnh native không bị chặn bởi các tính toán JS.

Kiến trúc Bridge hoạt động như thế nào

Bridge sử dụng ba cơ chế chính để giao tiếp: MessageQueue, tuần tự hóa JSON và gộp thông điệp (batching). MessageQueue là một thành phần nội bộ của React Native quản lý hàng đợi cuộc gọi giữa JS và phía native. Mỗi lời gọi phương thức native được đặt vào hàng đợi, tuần tự hóa và gửi theo lô để tối ưu hóa hiệu suất.

MessageQueue và tuần tự hóa

MessageQueue hoạt động theo nguyên lý gộp lô: các lời gọi phương thức native tích lũy và được gửi dưới dạng một nhóm duy nhất (lô) cứ sau 5–15 mili giây. Điều này làm giảm chi phí tuần tự hóa vì nhiều lời gọi được đóng gói trong một gói JSON duy nhất. Ở phía native, các thông điệp được giải tuần tự hóa và phân phối đến các mô-đun tương ứng.

Đăng ký mô-đun

Các mô-đun native được đăng ký tự động qua macro hoặc chú thích. iOS sử dụng macro RCT_EXPORT_MODULE, Android sử dụng chú thích @ReactMethod. React Native quét các mô-đun đã đăng ký khi khởi động ứng dụng và xây dựng một bản đồ JSON cấu hình của tất cả các phương thức có sẵn. Bản đồ này được truyền đến môi trường JS, và JavaScript biết được phương thức nào có thể được gọi.

Luồng dữ liệu

Dữ liệu đi theo đường dẫn sau: JavaScript gọi NativeModules.CalendarModule.createCalendarEvent(). Phương thức được tuần tự hóa thành một thông điệp JSON với định danh mô-đun, tên phương thức và đối số. Thông điệp đi vào MessageQueue. Trên luồng native, thông điệp được giải tuần tự hóa và chuyền đến mô-đun tương ứng. Kết quả thực thi được tuần tự hóa trở lại và gửi đến luồng JS dưới dạng Promise hoặc callback.

js
            // Native module call from JavaScript via Bridge
import { NativeModules } from 'react-native';

const CalendarModule = NativeModules.CalendarModule;

CalendarModule.createCalendarEvent('Test Event', 'Office')
  .then(eventId => {
    console.log('Created event with id:', eventId);
  })
  .catch(error => {
    console.error('Failed:', error);
  });

Ở phía native iOS, mô-đun trông giống một lớp Objective-C với macro RCT_EXPORT_MODULE. Phương thức được xuất bằng macro RCT_EXPORT_METHOD, và React Native tự động đăng ký nó trong Bridge. Các đối số được truyền theo vị trí và phải tương ứng với các kiểu JSON được hỗ trợ: NSString, NSNumber, NSArray, NSDictionary, BOOL.

objective-c
            // iOS Native Module registration in Bridge
@interface CalendarModule () RCT_EXPORT_MODULE()
@end

@implementation CalendarModule

RCT_EXPORT_METHOD(createCalendarEvent:(NSString *)name
                  location:(NSString *)location
                  resolver:(RCTPromiseResolveBlock)resolve
                  rejecter:(RCTPromiseRejectBlock)reject)
{
  NSNumber *eventId = createEvent(name, location);
  resolve(eventId);
}

@end

Hạn chế và vấn đề của Bridge

Bridge có một số hạn chế hiệu suất cơ bản. Chính là tính bất đồng bộ và tuần tự hóa bắt buộc. Mỗi lời gọi phương thức native chuyển đổi dữ liệu thành chuỗi JSON, làm tăng độ trễ và tiêu tốn bộ nhớ. Đối với các thao tác với khối lượng dữ liệu lớn, như xử lý hình ảnh hoặc làm việc với video, điều này trở thành nút cổ chai.

Chi phí tuần tự hóa

Việc tuần tự hóa và giải tuần tự hóa JSON tiêu tốn thời gian CPU và bộ nhớ. Mỗi thông điệp phải được chuyển đổi thành chuỗi ở phía JS, truyền qua cầu nối và phân tích ở phía native. Theo các thử nghiệm của Callstack (2022), việc tuần tự hóa một mảng 10.000 số qua Bridge mất khoảng 30–50 mili giây, điều không thể chấp nhận được đối với các cuộc gọi tần số cao.

Giới hạn kích thước thông điệp

Bridge không được tối ưu hóa để truyền dữ liệu nhị phân lớn. Ảnh, tệp âm thanh và luồng video yêu cầu các cách tiếp cận thay thế — ví dụ, ghi tệp vào đĩa và truyền đường dẫn dưới dạng chuỗi. Điều này tạo ra chi phí bổ sung cho các thao tác đọc và ghi hệ thống tệp.

  • Tính bất đồng bộ — Bridge không hỗ trợ các cuộc gọi đồng bộ, làm phức tạp các kịch bản yêu cầu phản hồi tức thì.
  • Bộ nhớ — mỗi thông điệp được lưu trong hàng đợi cho đến khi được xử lý, điều có thể dẫn đến tăng mức tiêu thụ bộ nhớ.
  • Gỡ lỗi — việc theo dõi thông điệp trong Bridge rất khó vì chuỗi cuộc gọi bị đứt giữa các luồng.

Nhận thức về những hạn chế này đã dẫn đến việc nhóm Meta phát triển một kiến trúc React Native mới, trong đó Bridge được thay thế bằng JSI (JavaScript Interface) và Turbo Module. JSI cho phép gọi các phương thức native trực tiếp, không cần tuần tự hóa, loại bỏ nhược điểm chính của Bridge.

Bridge so với Turbo Module: so sánh

So sánh Bridge và Turbo Module cho thấy sự khác biệt cơ bản trong cách tiếp cận kiến trúc. Bridge sử dụng hàng đợi thông điệp bất đồng bộ với tuần tự hóa JSON, trong khi Turbo Module hoạt động qua JSI — một giao diện trực tiếp giữa JavaScript và C++ cho phép gọi các phương thức native một cách đồng bộ mà không cần chuyển đổi dữ liệu.

Đặc điểmBridgeTurbo Module
Loại cuộc gọiBất đồng bộĐồng bộ và bất đồng bộ
Tuần tự hóaJSON ở mỗi cuộc gọiĐối tượng JSI không sao chép
Hiệu suấtTrung bìnhCao
KiểuĐộngTĩnh (Codegen)
TảiTất cả mô-đun khi khởi độngChậm (theo yêu cầu)

Việc lựa chọn giữa Bridge và Turbo Module phụ thuộc vào phiên bản React Native. Đối với các dự án trên React Native 0.72 trở về trước, Bridge vẫn là cơ chế chính. Bắt đầu từ React Native 0.73, Metro và kiến trúc mới được hỗ trợ song song, cho phép di chuyển dần dần. Việc chuyển đổi hoàn toàn sang Turbo Module yêu cầu nâng cấp lên React Native 0.76+ và kích hoạt kiến trúc mới trong cấu hình.

Ví dụ thiết lập Native Module qua Bridge

Hãy xem xét toàn bộ chu trình tạo và sử dụng Native Module qua Bridge với ví dụ mô-đun lịch. Mô-đun sẽ tạo một sự kiện và trả về định danh của nó. Ví dụ này bao gồm cài đặt cho cả hai nền tảng — iOS và Android.

Mô-đun Android

Trên Android, Native Module được tạo dưới dạng một lớp Java kế thừa ReactContextBaseJavaModule. Chú thích @ReactMethod xuất phương thức ra Bridge. Đối với Promise, giao diện Promise từ com.facebook.react.bridge được sử dụng.

java
public class CalendarModule extends ReactContextBaseJavaModule {

    @Override
    public String getName() {
        return "CalendarModule";
    }

    @ReactMethod
    public void createCalendarEvent(
            String name,
            String location,
            Promise promise) {
        try {
            Integer eventId = createCalendarEventNative(name, location);
            promise.resolve(eventId);
        } catch (Exception e) {
            promise.reject("EVENT_ERROR", e.getMessage());
        }
    }
}

Đăng ký và sử dụng

Mô-đun được đăng ký qua @ReactModule hoặc thủ công trong gói ứng dụng. React Native tự động phát hiện và thêm nó vào Bridge. Sau khi đăng ký, mô-đun có thể truy cập từ JavaScript qua NativeModules.

java
public class CalendarPackage implements ReactPackage {

    @Override
    public List<NativeModule> createNativeModules(
            ReactApplicationContext reactContext) {
        return Arrays.asList(
            new CalendarModule(reactContext)
        );
    }

    @Override
    public List<ViewManager> createViewManagers(
            ReactApplicationContext reactContext) {
        return Collections.emptyList();
    }
}

Điều quan trọng cần lưu ý là Bridge yêu cầu khởi động lại ứng dụng khi thêm mô-đun mới, vì bản đồ cấu hình được xây dựng một lần trong quá trình khởi tạo. Điều này phân biệt nó với Turbo Module, module này tải chậm và hỗ trợ tải lại nóng mô-đun mà không cần khởi động lại.

Câu hỏi thường gặp

Bridge khác với truyền dữ liệu trực tiếp như thế nào?

Bridge luôn sử dụng hàng đợi bất đồng bộ và tuần tự hóa JSON, trong khi truyền trực tiếp qua JSI hoạt động đồng bộ và không sao chép dữ liệu. Bridge tạo độ trễ tuần tự hóa nhưng đảm bảo cách ly luồng.

Có thể gọi phương thức đồng bộ qua Bridge không?

Không, Bridge chỉ hỗ trợ các cuộc gọi bất đồng bộ. Tương tác đồng bộ yêu cầu kiến trúc mới với JSI và Turbo Module. Đây là một trong những hạn chế chính đã được giải quyết trong React Native 0.76+.

Bridge hỗ trợ những kiểu dữ liệu nào?

Bridge hỗ trợ các kiểu có thể tuần tự hóa thành JSON: chuỗi, số, giá trị boolean, mảng, từ điển (đối tượng). Dữ liệu nhị phân như hình ảnh phải được truyền qua hệ thống tệp hoặc mã hóa base64.

Làm thế nào để đo hiệu suất của Bridge?

Để đo lường, hãy sử dụng React DevTools và trình phân tích React Native. Tab Performance hiển thị số lượng thông điệp trong hàng đợi Bridge và độ trễ. Gói react-native-bridge-spy cũng có sẵn để giám sát lưu lượng truy cập.

Khi nào nên chuyển từ Bridge sang Turbo Module?

Nên chuyển đối với các dự án đòi hỏi hiệu suất cao hoặc khi tạo ứng dụng mới trên React Native 0.76+. Đối với các dự án hiện có, việc di chuyển có thể dần dần — cả hai kiến trúc đều hoạt động song song.

Tổng kết

  • Bridge là cơ chế giao tiếp bất đồng bộ giữa JavaScript và mã native React Native, dựa trên tuần tự hóa JSON.
  • MessageQueue quản lý hàng đợi thông điệp, gộp các cuộc gọi thành lô để giảm chi phí.
  • Tuần tự hóa tạo độ trễ 30–50 ms khi truyền mảng dữ liệu lớn qua Bridge.
  • Hạn chế của kiến trúc bao gồm không có cuộc gọi đồng bộ và tiêu thụ bộ nhớ cao với các thông điệp thường xuyên.
  • Kiến trúc mới của React Native thay thế Bridge bằng JSI và Turbo Module, cung cấp quyền truy cập trực tiếp mà không cần tuần tự hóa.
  • Tương thích — Bridge tiếp tục hoạt động trong React Native đến 0.72+, và trong các phiên bản 0.73+ có sẵn hoạt động song song của cả hai kiến trúc.
  • Lựa chọn — đối với các dự án mới, kiến trúc mới được ưu tiên; các dự án hiện có di chuyển dần dần.

Chúng tôi sẽ phát triển ứng dụng di động chìa khóa trao tay

IT Sectr tạo các ứng dụng iOS và Android cho các công ty khởi nghiệp và doanh nghiệp từ năm 2017. Chúng tôi sẽ tư vấn và đề xuất giải pháp tốt nhất cho bạn.

Thảo luận dự án

Đọc thêm