Bridge är en arkitekturell komponent i React Native som möjliggör asynkron kommunikation mellan JavaScript-tråden och den inhemska miljön för iOS och Android. Den överför serialiserade JSON-meddelanden via en kö, vilket gör det möjligt att anropa inhemska API:er från JS-kod. Enligt Meta, 2024 förblir Bridge grunden för befintliga applikationer, även om den är sämre prestandamässigt jämfört med den nya arkitekturen baserad på JSI.
Huvudpunkter
Bridge (Bro) — är ett viktigt arkitekturellt element i React Native som möjliggör tvåvägs asynkron kommunikation mellan JavaScript-tråden, där applikationens affärslogik körs, och de inhemska trådarna för iOS och Android. Sedan lanseringen av React Native 2015 har Bridge varit det enda sättet för JS-kod att interagera med plattformens API:er — kamera, geolokalisering, filsystem, notifieringar och andra inhemska funktioner.
Bridge-arkitekturen är baserad på principen om meddelandekö (message queue). När JavaScript-kod anropar en inhemsk metod serialiseras begäran till en JSON-sträng, placeras i en kö och skickas asynkront till den inhemska sidan. Inhemsk kod bearbetar begäran, utför motsvarande operation och skickar tillbaka resultatet via samma kö till JS-tråden. Enligt Metas rapport på React Conf 2021 passerar upp till 10 000 meddelanden per sekund genom Bridge i en genomsnittlig applikation.
Huvudtrådarna som är involverade i Bridges funktion: JavaScript Thread (exekvering av JS-kod), Native Thread (exekvering av inhemska operationer) och Shadow Thread (beräkning av layout med hjälp av Yoga). Varje tråd arbetar oberoende, vilket säkerställer gränssnittets responsivitet — inhemska animationer blockeras inte av JS-beräkningar.
Bridge använder tre nyckelmekanismer för kommunikation: MessageQueue, JSON-serialisering och batchning av meddelanden. MessageQueue är en intern komponent i React Native som hanterar anropskön mellan JS och den inhemska sidan. Varje anrop till en inhemsk metod placeras i kön, serialiseras och skickas i batcher för prestandaoptimering.
MessageQueue fungerar enligt principen om batchning: anrop till inhemska metoder ackumuleras och skickas som en grupp (batch) var 5–15 millisekund. Detta minskar serialiseringsoverheaden eftersom flera anrop packas i ett JSON-paket. På den inhemska sidan deserialiseras meddelandena och distribueras till motsvarande moduler.
Inhemska moduler registreras automatiskt via makron eller annotationer. På iOS används makrot RCT_EXPORT_MODULE, på Android — annotationen @ReactMethod. React Native skannar de registrerade modulerna vid applikationsstart och bygger en konfigurations-JSON-karta över alla tillgängliga metoder. Denna karta överförs till JS-miljön, och JavaScript får veta vilka metoder som kan anropas.
Data går igenom följande väg: JavaScript anropar NativeModules.CalendarModule.createCalendarEvent(). Metoden serialiseras till ett JSON-meddelande med modulidentifierare, metodnamn och argument. Meddelandet hamnar i MessageQueue-kön. I den inhemska tråden deserialiseras meddelandet och skickas vidare till motsvarande modul. Resultatet av exekveringen serialiseras tillbaka och skickas till JS-tråden som ett Promise eller callback.
// Native module-anrop från JavaScript via Bridge
import { NativeModules } from 'react-native';
const CalendarModule = NativeModules.CalendarModule;
CalendarModule.createCalendarEvent('Test Event', 'Office')
.then(eventId => {
console.log('Händelse skapad med id:', eventId);
})
.catch(error => {
console.error('Misslyckades:', error);
});
På den inhemska iOS-sidan ser modulen ut som en Objective-C-klass med makrot RCT_EXPORT_MODULE. Metoden exporteras med makrot RCT_EXPORT_METHOD, och React Native registrerar den automatiskt i Bridge. Argument skickas efter position och måste motsvara de JSON-typer som stöds: NSString, NSNumber, NSArray, NSDictionary, BOOL.
// iOS Native Module-registrering i 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
Bridge har ett antal grundläggande prestandabegränsningar. Den främsta är obligatorisk asynkronicitet och serialisering. Varje anrop till en inhemsk metod omvandlar data till en JSON-sträng, vilket lägger till fördröjning och förbrukar minne. För operationer med stora datamängder, såsom bildbehandling eller arbete med video, blir detta en flaskhals.
JSON-serialisering och deserialisering tar processortid och minne. Varje meddelande måste omvandlas till en sträng på JS-sidan, skickas via bron och tolkas på den inhemska sidan. Enligt tester av Callstack (2022) tar serialisering av en array med 10 000 nummer via Bridge cirka 30–50 millisekunder, vilket är oacceptabelt för högfrekventa anrop.
Bridge är inte optimerad för att skicka stora binära data. Foton, ljudfiler och videoströmmar kräver alternativa tillvägagångssätt — till exempel att skriva filen till disk och skicka sökvägen som en sträng. Detta skapar extra overhead för läsning och skrivning av filsystemet.
Insikten om dessa begränsningar ledde Meta-teamet till att utveckla en ny React Native-arkitektur, där Bridge ersätts av JSI (JavaScript Interface) och Turbo Module. JSI möjliggör direkt anrop av inhemska metoder utan serialisering, vilket eliminerar Bridges största nackdel.
Jämförelsen av Bridge och Turbo Module visar grundläggande skillnader i arkitekturella tillvägagångssätt. Bridge använder en asynkron meddelandekö med JSON-serialisering, medan Turbo Module fungerar via JSI — ett direkt gränssnitt mellan JavaScript och C++ som möjliggör synkront anrop av inhemska metoder utan datakonvertering.
| Egenskap | Bridge | Turbo Module |
|---|---|---|
| Anropstyp | Asynkron | Synkron och asynkron |
| Serialisering | JSON vid varje anrop | JSI-objekt utan kopiering |
| Prestanda | Medel | Hög |
| Typning | Dynamisk | Statisk (Codegen) |
| Laddning | Alla moduler vid start | Lat (vid behov) |
Valet mellan Bridge och Turbo Module beror på React Native-versionen. För projekt på React Native 0.72 och äldre förblir Bridge den huvudsakliga mekanismen. Från och med React Native 0.73 stöds Metro och den nya arkitekturen parallellt, vilket möjliggör gradvis migrering. Fullständig övergång till Turbo Module kräver uppgradering till React Native 0.76+ och aktivering av den nya arkitekturen i konfigurationen.
Låt oss titta på hela cykeln för att skapa och använda en Native Module via Bridge med exemplet på en modul för att arbeta med en kalender. Modulen skapar en händelse och returnerar dess identifierare. Detta exempel omfattar konfiguration för båda plattformarna — iOS och Android.
På Android skapas Native Module som en Java-klass som ärver från ReactContextBaseJavaModule. Annotationen @ReactMethod exporterar metoden till Bridge. För Promise används Promise-gränssnittet från com.facebook.react.bridge.
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());
}
}
}
Modulen registreras via @ReactModule eller manuellt i applikationspaketet. React Native upptäcker den automatiskt och lägger till den i Bridge. Efter registrering är modulen tillgänglig från JavaScript via NativeModules.
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();
}
}
Det är viktigt att notera att Bridge kräver omstart av applikationen vid tillägg av nya moduler, eftersom konfigurationskartan byggs en gång under initialisering. Detta skiljer den från Turbo Module, som laddas lat och stöder hot-reload av moduler utan omstart.
Vanliga frågor
Bridge använder alltid en asynkron kö och JSON-serialisering, medan direkt överföring via JSI fungerar synkront och utan datakopiering. Bridge skapar fördröjning för serialisering men säkerställer isolering av trådar.
Nej, Bridge stöder endast asynkrona anrop. För synkron interaktion krävs den nya arkitekturen med JSI och Turbo Module. Detta är en av de viktigaste begränsningarna som har åtgärdats i React Native 0.76+.
Bridge stöder typer som kan serialiseras till JSON: strängar, siffror, boolean-värden, arrayer, ordböcker (objekt). Binära data som bilder måste skickas via filsystemet eller base64-kodning.
För mätning, använd React DevTools och React Native-profilern. Fliken Performance visar antalet meddelanden i Bridge-kön och fördröjningar. Paketet react-native-bridge-spy finns också tillgängligt för trafikövervakning.
Övergång rekommenderas för projekt som kräver hög prestanda eller vid skapande av nya applikationer på React Native 0.76+. För befintliga projekt kan migrering vara gradvis — båda arkitekturerna fungerar parallellt.
Sammanfattning
Vi utvecklar en mobil applikation nyckelfärdigt
IT Sectr skapar iOS- och Android-applikationer för startups och företag sedan 2017. Vi ger dig råd och föreslår den bästa lösningen.
Läs också