JSI (JavaScript Interface) — je softwarová vrstva v React Native, která poskytuje přímý synchronní přístup z JavaScriptu k C++ objektům a funkcím, a nahrazuje tak asynchronní JSON most Bridge. Na rozdíl od svého předchůdce, JSI umožňuje volat nativní metody bez serializace zpráv a předávat odkazy na C++ objekty přímo do JS prostředí. Podle údajů React Native Team (2025), JSI zajišťuje až 10násobné zrychlení interakce JS s nativním kódem ve scénářích s intenzivní výměnou dat.
Hlavní
JSI (JavaScript Interface) — je C++ vrstva, která dává JavaScriptovému engine (Hermes, JavaScriptCore, V8) možnost přímého přístupu k C++ objektům, funkcím a paměti. Na rozdíl od Bridge, který serializoval volání do JSON a přenášel je přes asynchronní frontu, JSI umožňuje JS kódu synchronně volat C++ metody a okamžitě získat výsledek.
JSI byla představena v React Native 0.64 jako součást nové architektury (New Architecture). Hlavním cílem bylo odstranění úzkého místa, kterým byl Bridge: každá interakce mezi JS a nativním kódem spotřebovávala čas na serializaci, deserializaci a přenos přes frontu zpráv. JSI řeší tento problém tím, že poskytuje JS engine přímý přístup k C++ objektům prostřednictvím obalů, které implementují rozhraní jsi::Value, jsi::Object a jsi::Function.
JSI není náhradou Bridge „jedna k jedné“ — je to zásadně odlišný přístup k integraci. Bridge fungoval jako poštovní schránka: JS odeslal zprávu, ta prošla frontou, nativní strana ji zpracovala a odeslala odpověď. JSI funguje jako ukazatel: JS obdrží odkaz na C++ objekt a může volat jeho metody synchronně, jako běžné JS funkce. To je zásadní rozdíl v architektuře interakce dvou prostředí.
Potřeba JSI vznikla z omezení původního Bridge, vytvořeného v React Native 2015. S rostoucí popularitou frameworku a složitostí aplikací se problém výkonu stal zjevným: každé volání nativního modulu vyžadovalo alespoň 3–5 ms na serializaci. Pro jednoduché operace, jako je čtení hodnoty senzoru nebo získávání velikosti obrazovky, to bylo přijatelné, ale pro animace, práci s grafikou a streamové zpracování dat — kritické. Tým React Native zahájil práci na nové architektuře v roce 2019 a JSI se stala jejím základem.
JSI je navržena jako abstrakce nad JavaScriptovými enginy. Poskytuje jednotné C++ API, které je implementováno pro každý konkrétní engine: Hermes, JavaScriptCore (iOS), V8 (Android). To znamená, že vývojář se nemusí starat o rozdíly mezi enginy — Fabric a TurboModules fungují stejně bez ohledu na to, který JS engine se používá.
Základem JSI je koncept Host Objects — C++ objektů, které jsou exportovány do JS prostředí jako nativní JS objekty. Když JS kód přistupuje k vlastnosti nebo metodě takového objektu, JSI zachytí volání a deleguje jej na příslušnou C++ metodu. To se děje synchronně, ve stejném vlákně, bez přepínání kontextu a bez alokace paměti pro JSON řetězec.
Každý Host Object implementuje rozhraní jsi::HostObject s metodami get, set a getPropertyNames. JS engine volá tyto metody při každém přístupu k vlastnostem objektu. Například při volání NativeModule.someMethod() v JS, JSI transformuje toto volání na C++ volání příslušné metody Host Object. Návratová hodnota je předána zpět do JS jako jsi::Value — zobecněný typ, který může představovat číslo, řetězec, booleovskou hodnotu, objekt nebo undefined.
Důležitou vlastností JSI je absence fronty zpráv. Bridge používal asynchronní frontu: JS odeslal požadavek, přepnul se na jiné úkoly, nativní strana požadavek zpracovala a výsledek se vrátil prostřednictvím callbacku. JSI funguje synchronně: pokud JS volá metodu nativního modulu prostřednictvím JSI, provádění JS kódu je pozastaveno, dokud není získán výsledek. To zjednodušuje logiku (není třeba čekat na callbacky) a odstraňuje race conditions, ale vyžaduje opatrnost — dlouhá synchronní volání blokují JS vlákno.
Hodnoty vytvořené prostřednictvím JSI žijí v běhovém prostředí JS engine a jsou spravovány garbage collectorem. Když C++ kód vytvoří jsi::String nebo jsi::Object a vrátí jej do JS, prostředí automaticky spravuje paměť. Pokud C++ kód chce uchovat odkaz na JS hodnotu mezi voláními, použije jsi::Value::getWeak() nebo globální jsi::Object::setProperty s uchováním odkazu na kořenovém objektu runtime. To zabraňuje předčasnému odstranění garbage collectorem.
JSI není standardně bezpečná pro vlákna. Všechna volání metod JSI musí pocházet z vlákna, ve kterém je spouštěn JS (obvykle je to JS vlákno React Native). Pokud nativní modul spouští práci na pozadí v samostatném vlákně, výsledek musí být předán zpěty přes JS vlákno pomocí volání runOnJS z TurboModules. Toto omezení je cenou za synchronnost a absenci serializace.
Rozdíl mezi JSI a Bridge má zásadní charakter a ovlivňuje všechny aspekty interakce JS s nativním kódem. Bridge byl asynchronní, serializoval data do JSON a používal frontu zpráv; JSI je synchronní, pracuje s nativními odkazy a nevyžaduje serializaci.
| Parametr | Bridge | JSI |
|---|---|---|
| Model volání | Asynchronní fronta | Synchronní přímé volání |
| Serializace | JSON (serializace + deserializace) | Žádná (přímé odkazy na C++ objekty) |
| Zpoždění | 3–10 ms na volání | 0.1–0.5 ms na volání |
| Typování | Dynamické (přes JSON) | Statické (přes Codegen) |
| C++ integrace | Pouze přes nativní moduly (Java/ObjC) | Přímá, bez zprostředkovatelů |
| Vlákno | Samostatné nativní vlákno | JS vlákno (synchronně) |
Podle údajů React Native Team, migrace z Bridge na JSI v aplikaci Facebook Marketplace zkrátila dobu spouštění o 35 % a snížila spotřebu paměti o 20 % díky eliminaci duplikace dat mezi JS a nativní stranou.
Bridge nebyl „chybou“ — bylo to architektonické rozhodnutí odůvodněné v době vzniku React Native v roce 2015. Nativní vývoj pro dvě platformy s různými jazyky vyžadoval univerzální formát výměny. JSON jako formát serializace byl dostupný na všech platformách a umožňoval sjednocení interakce. Problém se projevil později, když se React Native začal používat pro složité aplikace s tisíci volání nativních modulů za sekundu.
React Native zachovává zpětnou kompatibilitu: nativní moduly napsané pro Bridge nadále fungují v nové architektuře prostřednictvím vrstvy kompatibility. U nových modulů se však doporučuje okamžité použití JSI přes TurboModules. Migrace stávajících modulů spočívá ve výměně protokolu interakce bez změny business logiky samotného modulu.
JSI je základní vrstva, na které jsou postaveny všechny komponenty nové architektury React Native. Bez JSI by nemohl fungovat ani Fabric (nový renderer) ani TurboModules (optimalizované nativní moduly). JSI poskytuje jednotný způsob interakce JS s C++ na všech úrovních.
Fabric — nový renderer React Native, který používá JSI pro synchronní přístup k C++ reprezentacím UI. Ve staré architektuře procházelo vykreslování přes Bridge: JS vytvořil React elementy, serializoval je do JSON, odeslal přes Bridge, nativní strana deserializovala a vytvořila UI. Fabric prostřednictvím JSI vytváří C++ Shadow Tree objekty přímo z JS, synchronně vypočítává Layout přes Yoga a předává hotové rámce nativnímu rendereru — bez jediné serializace.
TurboModules — je evoluce nativních modulů React Native. Místo registrace modulu v Bridge a volání jeho metod přes JSON, TurboModules používá JSI pro líné načítání a přímé volání. Když JS kód poprvé přistoupí k modulu, JSI vytvoří Host Object — ten načte nativní modul a poskytne jeho metody jako C++ funkce. Líné načítání znamená, že modul nespotřebovává paměť až do prvního použití — to je důležité zejména v aplikacích s desítkami nativních modulů, z nichž mnohé se používají pouze na určitých obrazovkách.
Pro práci s JSI v nové architektuře se používá Codegen — nástroj, který generuje C++ obaly z JavaScriptových specifikací. Vývojář popíše rozhraní nativního modulu v TypeScript nebo Flow a Codegen vygeneruje C++ kód, který implementuje Host Object kompatibilní s JSI. To automatizuje rutinní práci a zaručuje, že typy na straně JS a C++ jsou synchronizované.
Podívejme se, jak vypadá práce s JSI v praxi. V tomto příkladu se vytváří jednoduchá C++ třída, která je exportována do JS prostřednictvím JSI, a její metoda je volána z JavaScript kódu React Native.
// Calculator.h — hlavička C++ třídy přístupná z JS
class Calculator {
public:
double add(double a, double b) { return a + b; }
double multiply(double a, double b) { return a * b; }
};
Třída Calculator obsahuje dvě aritmetické metody. Musíme ji zpřístupnit z JS. Za tímto účelem vytvoříme Host Object, který obalí Calculator a poskytuje jeho metody prostřednictvím JSI.
// CalculatorHostObject.cpp — implementace JSI obalu
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();
}
};
V tomto kódu je metoda get volána pokaždé, když JS přistupuje k vlastnosti objektu. Pokud je název vlastnosti „add“, je vrácena C++ funkce, která přijímá dva argumenty z JS a volá calc.add(). Hodnota je vracena jako jsi::Value — JSI automaticky převádí double na JS číslo.
Po registraci Host Object v JS prostředí vypadá volání jako běžná JS funkce. Všechny typy jsou kontrolovány ve fázi generování kódu, což eliminuje chyby neshody typů během provádění.
// JavaScript — volání C++ kalkulačky přes JSI
import { Calculator } from 'react-native-calculator'
const result = Calculator.add(5, 3)
console.log(result) // 8 — synchronně, bez zpoždění
const product = Calculator.multiply(4, 2.5)
console.log(product) // 10 — okamžitý výsledek
Všimněte si: výsledek je vrácen okamžitě, bez Promise, bez await, bez callbacků. To je synchronní volání, které bylo v architektuře Bridge nemožné. Pro dlouhodobé operace (čtení souboru, síťový požadavek) je třeba použít asynchronní vzory — JSI neodstraňuje potřebu vláken na pozadí pro těžké úkoly.
V praxi většina vývojářů nepíše JSI Host Objects ručně — tuto práci vykonává Codegen, který generuje C++ obaly na základě TypeScript specifikací. Nicméně porozumění tomu, jak JSI funguje pod kapotou, je nezbytné pro efektivní ladění výkonu a při vytváření složitých nativních modulů, které vyžadují přímý přístup k C++ knihovnám (Skia, FFmpeg, OpenCV).
Často kladené otázky
Bridge funguje asynchronně prostřednictvím JSON serializace a fronty zpráv — každé volání vyžaduje 3–10 ms na konverzi dat. JSI poskytuje synchronní přímý přístup k C++ objektům bez serializace, čímž snižuje zpoždění na 0.1–0.5 ms. JSI také podporuje předávání odkazů na objekty, nikoli jejich kopií.
Ano, JSI poskytuje jednotné C++ API, které je implementováno pro Hermes (výchozí v React Native), JavaScriptCore (iOS) a V8 (Android). Vývojář nemusí psát různý kód pro různé enginy — Fabric a TurboModules fungují stejně na všech podporovaných enginech.
Ano, React Native poskytuje vrstvu zpětné kompatibility. Nativní moduly napsané pro Bridge nadále fungují v nové architektuře. Doporučuje se však migrovat je na TurboModules pro získání výhod JSI — líného načítání a synchronních volání.
Pro každodenní vývoj — ne. TypeScript specifikace nativních modulů jsou automaticky kompilovány do C++ obalů prostřednictvím Codegen. Znalost C++ je potřeba pouze při vytváření vlastních C++ knihoven nebo při ladění výkonu JSI na úrovni runtime.
JSI řeší tři klíčové problémy Bridge: vysoké zpoždění kvůli JSON serializaci, chybějící synchronní volání a nemožnost předávat složité objekty odkazem. JSI také umožňuje přímou integraci C++ knihoven bez vrstvy Java nebo Objective-C.
Shrnutí
Vyvineme mobilní aplikaci na klíč
IT Sectr vytváří aplikace pro iOS a Android pro startupy a podniky od roku 2017. Poradíme vám a navrhneme nejlepší řešení.
Přečtěte si také