JSI (JavaScript Interface) — är en programvarulager i React Native som ger direkt synkron åtkomst från JavaScript till C++-objekt och funktioner, och ersätter den asynkrona JSON-bryggan Bridge. Till skillnad från sin föregångare tillåter JSI anrop av nativa metoder utan serialisering av meddelanden och överföring av referenser till C++-objekt direkt till JS-miljön. Enligt uppgifter från React Native Team (2025), ger JSI upp till 10 gångers acceleration av JS-interaktion med nativ kod i scenarier med intensivt datautbyte.
Huvudsakliga
JSI (JavaScript Interface) — är ett C++-lager som ger JavaScript-motorn (Hermes, JavaScriptCore, V8) möjlighet att direkt komma åt C++-objekt, funktioner och minne. Till skillnad från Bridge, som serialiserade anrop till JSON och överförde dem via en asynkron kö, tillåter JSI JS-kod att synkront anropa C++-metoder och omedelbart få resultatet.
JSI introducerades i React Native 0.64 som en del av den nya arkitekturen (New Architecture). Huvudmålet var att eliminera flaskhalsen som Bridge utgjorde: varje interaktion mellan JS och nativ kod förbrukade tid på serialisering, deserialisering och överföring via meddelandekön. JSI löser detta problem genom att ge JS-motorn direkt åtkomst till C++-objekt via omslag som implementerar gränssnitten jsi::Value, jsi::Object och jsi::Function.
JSI är inte en „en-till-en”-ersättning för Bridge — det är ett fundamentalt annorlunda synsätt på integration. Bridge fungerade som en brevlåda: JS skickade ett meddelande, det gick genom kön, den nativa sidan bearbetade det och skickade ett svar. JSI fungerar som en pekare: JS får en referens till ett C++-objekt och kan anropa dess metoder synkront, precis som vanliga JS-funktioner. Detta är den grundläggande skillnaden i arkitekturen för interaktion mellan två miljöer.
Behovet av JSI uppstod på grund av begränsningarna hos den ursprungliga Bridge, som skapades i React Native 2015. I takt med att ramverkets popularitet ökade och applikationerna blev mer komplexa, blev prestandaproblemet uppenbart: varje anrop till en nativ modul krävde minst 3–5 ms för serialisering. För enkla operationer, som att läsa ett sensorvärde eller hämta skärmstorleken, var detta acceptabelt, men för animationer, grafikarbete och strömmande databehandling — kritiskt. React Native-teamet började arbeta på den nya arkitekturen 2019, och JSI blev dess grund.
JSI är utformad som en abstraktion över JavaScript-motorer. Den tillhandahåller ett enhetligt C++-API som implementeras för varje specifik motor: Hermes, JavaScriptCore (iOS), V8 (Android). Detta innebär att utvecklaren inte behöver oroa sig för skillnader mellan motorer — Fabric och TurboModules fungerar på samma sätt oavsett vilken JS-motor som används.
Grunden för JSI är konceptet Host Objects — C++-objekt som exporteras till JS-miljön som nativa JS-objekt. När JS-kod når en egenskap eller metod hos ett sådant objekt, fångar JSI upp anropet och delegerar det till motsvarande C++-metod. Detta sker synkront, i samma tråd, utan kontextväxling och utan minnesallokering för en JSON-sträng.
Varje Host Object implementerar gränssnittet jsi::HostObject med metoderna get, set och getPropertyNames. JS-motorn anropar dessa metoder vid varje åtkomst till objektets egenskaper. Till exempel, vid anrop av NativeModule.someMethod() i JS, omvandlar JSI detta anrop till ett C++-anrop av motsvarande metod i Host Object. Returvärdet skickas tillbaka till JS som jsi::Value — en generaliserad typ som kan representera ett tal, en sträng, ett booleskt värde, ett objekt eller undefined.
En viktig egenskap hos JSI är frånvaron av meddelandekö. Bridge använde en asynkron kö: JS skickade en begäran, växlade till andra uppgifter, den nativa sidan bearbetade begäran och resultatet kom tillbaka via en callback. JSI fungerar synkront: om JS anropar en metod i en nativ modul via JSI, pausas exekveringen av JS-koden tills resultatet har erhållits. Detta förenklar logiken (man behöver inte vänta på callbacks) och eliminerar race conditions, men kräver försiktighet — långa synkrona anrop blockerar JS-tråden.
Värden som skapas via JSI lever i JS-motorns runtime-miljö och hanteras av skräpinsamlaren. När C++-kod skapar ett jsi::String eller jsi::Object och returnerar det till JS, hanterar miljön automatiskt minnet. Om C++-kod vill behålla en referens till ett JS-värde mellan anrop, används jsi::Value::getWeak() eller global jsi::Object::setProperty med bevarande av referensen på runtime-objektets rot. Detta förhindrar förtidig borttagning av skräpinsamlaren.
JSI är inte standardmässigt trådsäker. Alla anrop av JSI-metoder måste komma från den tråd där JS exekveras (vanligtvis är detta React Native JS-tråd). Om en nativ modul startar bakgrundsarbete i en separat tråd, måste resultatet skickas tillbaka via JS-tråden med hjälp av anropet runOnJS från TurboModules. Denna begränsning är priset för synkronicitet och frånvaro av serialisering.
Skillnaden mellan JSI och Bridge är av grundläggande karaktär och påverkar alla aspekter av interaktionen mellan JS och nativ kod. Bridge var asynkron, serialiserade data till JSON och använde en meddelandekö; JSI är synkron, arbetar med nativa referenser och kräver ingen serialisering.
| Parameter | Bridge | JSI |
|---|---|---|
| Anropsmodell | Asynkron kö | Synkront direktanrop |
| Serialisering | JSON (serialisering + deserialisering) | Ingen (direkta referenser till C++-objekt) |
| Fördröjning | 3–10 ms per anrop | 0.1–0.5 ms per anrop |
| Typning | Dynamisk (via JSON) | Statisk (via Codegen) |
| C++-integration | Endast via nativa moduler (Java/ObjC) | Direkt, utan mellanhänder |
| Tråd | Separat nativ tråd | JS-tråd (synkront) |
Enligt uppgifter från React Native Team, minskade migreringen från Bridge till JSI i Facebook Marketplace-appen starttiden med 35% och minskade minnesförbrukningen med 20% tack vare eliminering av dataduplicering mellan JS och den nativa sidan.
Bridge var inte ett „misstag” — det var ett arkitektoniskt beslut som var motiverat vid tiden för skapandet av React Native 2015. Native utveckling för två plattformar med olika språk krävde ett universellt utbytesformat. JSON som serialiseringsformat var tillgängligt på alla plattformar och möjliggjorde enhetliggörande av interaktionen. Problemet visade sig senare, när React Native började användas för komplexa applikationer med tusentals anrop till nativa moduler per sekund.
React Native behåller bakåtkompatibilitet: nativa moduler skrivna för Bridge fortsätter att fungera i den nya arkitekturen genom ett kompatibilitetslager. För nya moduler rekommenderas dock att omedelbart använda JSI via TurboModules. Migrering av befintliga moduler består av att byta interaktionsprotokoll utan att ändra modulens affärslogik.
JSI är det grundläggande lagret som alla komponenter i den nya React Native-arkitekturen är byggda på. Utan JSI skulle varken Fabric (den nya renderaren) eller TurboModules (optimerade nativa moduler) kunna fungera. JSI tillhandahåller ett enhetligt sätt för interaktion mellan JS och C++ på alla nivåer.
Fabric — den nya React Native-renderaren som använder JSI för synkron åtkomst till C++-representationer av UI. I den gamla arkitekturen gick rendering via Bridge: JS skapade React-element, serialiserade dem till JSON, skickade via Bridge, den nativa sidan deserialiserade och skapade UI. Fabric skapar via JSI C++ Shadow Tree-objekt direkt från JS, beräknar synkront Layout via Yoga och överför färdiga ramar till den nativa renderaren — utan någon serialisering.
TurboModules — är evolutionen av React Native nativa moduler. Istället för att registrera modulen i Bridge och anropa dess metoder via JSON, använder TurboModules JSI för lat laddning och direkt anrop. När JS-kod första gången når en modul, skapar JSI ett Host Object — det laddar den nativa modulen och tillhandahåller dess metoder som C++-funktioner. Lat laddning innebär att modulen inte förbrukar minne förrän första användningen — detta är särskilt viktigt i applikationer med dussintals nativa moduler, varav många endast används på vissa skärmar.
För arbete med JSI i den nya arkitekturen används Codegen — ett verktyg som genererar C++-omslag från JavaScript-specifikationer. Utvecklaren beskriver gränssnittet för den nativa modulen i TypeScript eller Flow, och Codegen genererar C++-kod som implementerar en JSI-kompatibel Host Object. Detta automatiserar rutinarbete och garanterar att typerna på JS- och C++-sidan är synkroniserade.
Låt oss se hur arbetet med JSI ser ut i praktiken. I detta exempel skapas en enkel C++-klass som exporteras till JS via JSI, och dess metod anropas från JavaScript-kod i React Native.
// Calculator.h — C++-klasshuvud tillgängligt från JS
class Calculator {
public:
double add(double a, double b) { return a + b; }
double multiply(double a, double b) { return a * b; }
};
Klassen Calculator innehåller två aritmetiska metoder. Vi måste göra den tillgänglig från JS. För detta skapar vi ett Host Object som omsluter Calculator och tillhandahåller dess metoder via JSI.
// CalculatorHostObject.cpp — implementering av JSI-omslag
class CalculatorHostObject : public jsi::HostObject {
private:
Calculator calc;
public:
jsi::Value get(jsi::Runtime& runtime,
const jsi::PropNameID& name) override {
auto propName = name.utf8(runtime);
if (propName == "add") {
return jsi::Function::createFromHostFunction(
runtime, name, 2,
[this](jsi::Runtime& runtime,
const jsi::Value& thisVal,
const jsi::Value* args,
size_t count) -> jsi::Value {
return jsi::Value(calc.add(
args[0].asNumber(),
args[1].asNumber()));
});
}
return jsi::Value::undefined();
}
};
I denna kod anropas metoden get varje gång JS når en egenskap hos objektet. Om egenskapens namn är „tillägg” returneras en C++-funktion som tar emot två argument från JS och anropar calc.add(). Värdet returneras som jsi::Value — JSI konverterar automatiskt double till ett JS-tal.
Efter registrering av Host Object i JS-miljön ser anropet ut som en vanlig JS-funktion. Alla typer kontrolleras i kodgenereringsfasen, vilket eliminerar typmatchningsfel under exekveringen.
// JavaScript — anropa C++-kalkylator via JSI
import { Calculator } from 'react-native-calculator'
const result = Calculator.add(5, 3)
console.log(result) // 8 — synkront, ingen fördröjning
const product = Calculator.multiply(4, 2.5)
console.log(product) // 10 — omedelbart resultat
Observera: resultatet returneras omedelbart, utan Promise, utan await, utan callbacks. Detta är ett synkront anrop, som var omöjligt i Bridge-arkitekturen. För långvariga operationer (filläsning, nätverksbegäran) bör asynkrona mönster användas — JSI eliminerar inte behovet av bakgrundstrådar för tunga uppgifter.
I praktiken skriver de flesta utvecklare inte JSI Host Objects manuellt — detta arbete utförs av Codegen, som genererar C++-omslag baserat på TypeScript-specifikationer. Men förståelse för hur JSI fungerar under huven är nödvändig för effektiv prestandafelsökning och vid skapande av komplexa nativa moduler som kräver direkt åtkomst till C++-bibliotek (Skia, FFmpeg, OpenCV).
Vanliga frågor
Bridge fungerar asynkront via JSON-serialisering och en meddelandekö — varje anrop kräver 3–10 ms för datakonvertering. JSI ger synkron direkt åtkomst till C++-objekt utan serialisering, vilket minskar fördröjningen till 0.1–0.5 ms. JSI stöder också överföring av referenser till objekt, inte deras kopior.
Ja, JSI tillhandahåller ett enhetligt C++-API som är implementerat för Hermes (standard i React Native), JavaScriptCore (iOS) och V8 (Android). Utvecklaren behöver inte skriva olika kod för olika motorer — Fabric och TurboModules fungerar på samma sätt på alla motorer som stöds.
Ja, React Native tillhandahåller ett bakåtkompatibilitetslager. Native moduler skrivna för Bridge fortsätter att fungera i den nya arkitekturen. Det rekommenderas dock att migrera dem till TurboModules för att dra nytta av JSI:s fördelar — lat laddning och synkrona anrop.
För daglig utveckling — nej. TypeScript-specifikationerna för nativa moduler kompileras automatiskt till C++-omslag via Codegen. C++-kunskaper behövs endast när man skapar egna C++-bibliotek eller vid felsökning av JSI prestanda på runtime-nivå.
JSI löser tre viktiga problem med Bridge: hög fördröjning på grund av JSON-serialisering, brist på synkrona anrop och oförmåga att överföra komplexa objekt via referens. JSI möjliggör också direkt integration av C++-bibliotek utan Java- eller Objective-C-lager.
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å