JSI (JavaScript Interface) হল React Native-এর একটি সফটওয়্যার লেয়ার যা JavaScript থেকে C++ অবজেক্ট এবং ফাংশনে সরাসরি সিনক্রোনাস অ্যাক্সেস প্রদান করে, যা অ্যাসিনক্রোনাস JSON ব্রিজ Bridge-কে প্রতিস্থাপন করে। এর পূর্বসূরীর থেকে ভিন্ন, JSI বার্তা সিরিয়ালাইজেশন ছাড়াই নেটিভ মেথড কল করতে এবং C++ অবজেক্টের রেফারেন্স সরাসরি JS পরিবেশে পাঠাতে দেয়। React Native টিম (2025)-এর মতে, JSI ডেটা-নিবিড় পরিস্থিতিতে JS-নেটিভ কোড মিথস্ক্রিয়ায় 10 গুণ পর্যন্ত ত্বরণ প্রদান করে।
মূল পয়েন্ট
JSI (JavaScript Interface) হল একটি C++ লেয়ার যা JavaScript ইঞ্জিনকে (Hermes, JavaScriptCore, V8) C++ অবজেক্ট, ফাংশন এবং মেমোরিতে সরাসরি অ্যাক্সেস করার ক্ষমতা প্রদান করে। Bridge-এর বিপরীতে, যা কলগুলিকে JSON-এ সিরিয়ালাইজ করত এবং অ্যাসিনক্রোনাস সারির মাধ্যমে পাঠাত, JSI JS কোডকে সিনক্রোনাসভাবে C++ মেথড কল করতে এবং অবিলম্বে ফলাফল পেতে দেয়।
JSI React Native 0.64-এ নতুন আর্কিটেকচারের (New Architecture) অংশ হিসেবে প্রবর্তিত হয়েছিল। মূল লক্ষ্য ছিল Bridge-এর প্রতিনিধিত্বকারী বাধা দূর করা: JS এবং নেটিভ কোডের মধ্যে প্রতিটি মিথস্ক্রিয়া সিরিয়ালাইজেশন, ডিসিরিয়ালাইজেশন এবং বার্তা সারির মাধ্যমে যেতে সময় নিত। JSI jsi::Value, jsi::Object এবং jsi::Function ইন্টারফেস বাস্তবায়নকারী র্যাপারের মাধ্যমে JS ইঞ্জিনকে C++ অবজেক্টে সরাসরি অ্যাক্সেস দিয়ে এই সমস্যার সমাধান করে।
JSI হল Bridge-এর এক-থেকে-এক প্রতিস্থাপন নয় — এটি একীকরণের জন্য একটি মৌলিকভাবে ভিন্ন পদ্ধতি। Bridge একটি মেলবক্সের মতো কাজ করত: JS একটি বার্তা পাঠাত, এটি একটি সারির মাধ্যমে যেত, নেটিভ পক্ষ এটি প্রক্রিয়া করত এবং উত্তর পাঠাত। JSI একটি পয়েন্টারের মতো কাজ করে: JS একটি C++ অবজেক্টের রেফারেন্স পায় এবং সাধারণ JS ফাংশনের মতো সিনক্রোনাসভাবে এর মেথড কল করতে পারে। এটি দুটি পরিবেশের মধ্যে মিথস্ক্রিয়া আর্কিটেকচারে একটি মৌলিক পার্থক্য।
JSI-এর প্রয়োজনীয়তা মূল Bridge-এর সীমাবদ্ধতা থেকে উদ্ভূত হয়েছিল, যা React Native 2015-এ প্রতিষ্ঠিত হয়েছিল। ফ্রেমওয়ার্কের জনপ্রিয়তা বৃদ্ধি এবং অ্যাপ্লিকেশন জটিল হওয়ার সাথে সাথে পারফরম্যান্স সমস্যা স্পষ্ট হয়ে ওঠে: প্রতিটি নেটিভ মডিউল কলের জন্য সিরিয়ালাইজেশনে কমপক্ষে 3–5 ms প্রয়োজন ছিল। সহজ অপারেশন যেমন সেন্সর মান পড়া বা স্ক্রিন সাইজ পাওয়ার জন্য এটি গ্রহণযোগ্য ছিল, কিন্তু অ্যানিমেশন, গ্রাফিক্স কাজ এবং স্ট্রিমিং ডেটা প্রক্রিয়াকরণের জন্য এটি গুরুত্বপূর্ণ ছিল। React Native টিম 2019 সালে নতুন আর্কিটেকচারে কাজ শুরু করে এবং JSI তার ভিত্তি হয়ে ওঠে।
JSI JavaScript ইঞ্জিনের উপর একটি অ্যাবস্ট্রাকশন লেয়ার হিসাবে ডিজাইন করা হয়েছে। এটি একটি ইউনিফাইড C++ API প্রদান করে যা প্রতিটি নির্দিষ্ট ইঞ্জিনের জন্য বাস্তবায়িত হয়: Hermes, JavaScriptCore (iOS), V8 (Android)। এর মানে হল ডেভেলপারদের ইঞ্জিনের মধ্যে পার্থক্য নিয়ে চিন্তা করতে হবে না — Fabric এবং TurboModules সব সমর্থিত ইঞ্জিনে একইভাবে কাজ করে।
JSI-এর মূলে রয়েছে হোস্ট অবজেক্ট (Host Objects) ধারণা — C++ অবজেক্ট যা JS পরিবেশে নেটিভ JS অবজেক্ট হিসেবে রপ্তানি করা হয়। যখন JS কোড এই ধরনের অবজেক্টের একটি প্রপার্টি বা মেথড অ্যাক্সেস করে, JSI কলটি আটকায় এবং সংশ্লিষ্ট C++ মেথডে অর্পণ করে। এটি সিনক্রোনাসভাবে, একই থ্রেডে, প্রসঙ্গ সুইচিং ছাড়া এবং JSON স্ট্রিংয়ের জন্য মেমোরি বরাদ্দ না করেই ঘটে।
প্রতিটি হোস্ট অবজেক্ট jsi::HostObject ইন্টারফেসটি get, set এবং getPropertyNames মেথড সহ বাস্তবায়ন করে। JS ইঞ্জিন প্রতিবার অবজেক্টের একটি প্রপার্টি অ্যাক্সেস করার সময় এই মেথডগুলি কল করে। উদাহরণস্বরূপ, JS-এ NativeModule.someMethod() কল করার সময়, JSI এই কলটিকে সংশ্লিষ্ট হোস্ট অবজেক্ট মেথডের C++ কল-এ রূপান্তর করে। রিটার্ন মান jsi::Value হিসাবে JS-এ ফেরত পাঠানো হয় — একটি জেনেরিক টাইপ যা সংখ্যা, স্ট্রিং, বুলিয়ান, অবজেক্ট বা undefined উপস্থাপন করতে পারে।
JSI-এর একটি গুরুত্বপূর্ণ বৈশিষ্ট্য হল বার্তা সারির অনুপস্থিতি। Bridge একটি অ্যাসিনক্রোনাস সারি ব্যবহার করত: JS একটি অনুরোধ পাঠাত, অন্যান্য কাজে স্যুইচ করত, নেটিভ পক্ষ অনুরোধ প্রক্রিয়া করত এবং ফলাফল কলব্যাকের মাধ্যমে ফেরত আসত। JSI সিনক্রোনাসভাবে কাজ করে: যদি JS JSI-এর মাধ্যমে একটি নেটিভ মডিউল মেথড কল করে, JS কোড নির্বাহ ফলাফল প্রাপ্ত না হওয়া পর্যন্ত থামে। এটি লজিক সরল করে (কলব্যাকের জন্য অপেক্ষার প্রয়োজন নেই) এবং রেস কন্ডিশন দূর করে, কিন্তু সতর্কতা প্রয়োজন — দীর্ঘ সিনক্রোনাস কল JS থ্রেড ব্লক করে।
JSI-এর মাধ্যমে তৈরি মানগুলি JS ইঞ্জিন রানটাইমে বাস করে এবং আবর্জনা সংগ্রহকারী দ্বারা পরিচালিত হয়। যখন C++ কোড jsi::String বা jsi::Object তৈরি করে এবং JS-এ ফেরত দেয়, পরিবেশ স্বয়ংক্রিয়ভাবে মেমোরি পরিচালনা করে। যদি C++ কোড কলগুলির মধ্যে একটি JS মানের রেফারেন্স রাখতে চায়, তাহলে jsi::Value::getWeak() বা রানটাইম রুট অবজেক্টে সংরক্ষিত রেফারেন্স সহ গ্লোবাল jsi::Object::setProperty ব্যবহার করা হয়। এটি অকাল আবর্জনা সংগ্রহ প্রতিরোধ করে।
JSI ডিফল্টরূপে থ্রেড-নিরাপদ নয়। সমস্ত JSI মেথড কল সেই থ্রেড থেকে হতে হবে যেখানে JS নির্বাহ হয় (সাধারণত React Native-এর JS থ্রেড)। যদি কোনো নেটিভ মডিউল আলাদা থ্রেডে ব্যাকগ্রাউন্ড কাজ শুরু করে, তাহলে ফলাফল TurboModules থেকে runOnJS ব্যবহার করে JS থ্রেড-এর মাধ্যমে ফেরত পাঠাতে হবে। এই সীমাবদ্ধতা হল সিনক্রোনিসিটি এবং সিরিয়ালাইজেশনের অনুপস্থিতির মূল্য।
JSI এবং Bridge-এর মধ্যে পার্থক্য মৌলিক এবং JS-নেটিভ কোড মিথস্ক্রিয়ার সমস্ত দিককে প্রভাবিত করে। Bridge ছিল অ্যাসিনক্রোনাস, ডেটা JSON-এ সিরিয়ালাইজ করত এবং বার্তা সারি ব্যবহার করত; JSI হল সিনক্রোনাস, নেটিভ রেফারেন্স নিয়ে কাজ করে এবং সিরিয়ালাইজেশনের প্রয়োজন নেই।
| প্যারামিটার | Bridge | JSI |
|---|---|---|
| কল মডেল | অ্যাসিনক্রোনাস সারি | সিনক্রোনাস সরাসরি কল |
| সিরিয়ালাইজেশন | JSON (সিরিয়ালাইজেশন + ডিসিরিয়ালাইজেশন) | কোনোটিই নয় (C++ অবজেক্টে সরাসরি রেফারেন্স) |
| লেটেন্সি | প্রতি কল 3–10 ms | প্রতি কল 0.1–0.5 ms |
| টাইপিং | ডায়নামিক (JSON-এর মাধ্যমে) | স্ট্যাটিক (Codegen-এর মাধ্যমে) |
| C++ ইন্টিগ্রেশন | শুধুমাত্র নেটিভ মডিউলের মাধ্যমে (Java/ObjC) | সরাসরি, কোন মধ্যস্থতাকারী নেই |
| থ্রেড | পৃথক নেটিভ থ্রেড | JS থ্রেড (সিনক্রোনাস) |
React Native টিম-এর মতে, Facebook Marketplace অ্যাপে Bridge থেকে JSI-তে মাইগ্রেশন JS এবং নেটিভ পক্ষের মধ্যে ডেটা ডুপ্লিকেশন দূর করে স্টার্টআপ সময় 35% কমিয়েছে এবং মেমোরি খরচ 20% হ্রাস করেছে।
Bridge কোনো “ভুল” ছিল না — এটি React Native 2015-এর সৃষ্টির সময় ন্যায্য একটি আর্কিটেকচারাল সিদ্ধান্ত ছিল। দুটি ভিন্ন ভাষার প্ল্যাটফর্মের জন্য নেটিভ ডেভেলপমেন্টের একটি সার্বজনীন বিনিময় বিন্যাস প্রয়োজন ছিল। JSON একটি সিরিয়ালাইজেশন বিন্যাস হিসাবে সমস্ত প্ল্যাটফর্মে উপলব্ধ ছিল এবং মিথস্ক্রিয়াকে একীভূত করার অনুমতি দেয়। সমস্যাটি পরে স্পষ্ট হয়, যখন React Native প্রতি সেকেন্ডে হাজার হাজার নেটিভ মডিউল কল সহ জটিল অ্যাপ্লিকেশনের জন্য ব্যবহার করা শুরু হয়।
React Native পশ্চাদগামী সামঞ্জস্যতা বজায় রাখে: Bridge-এর জন্য লেখা নেটিভ মডিউলগুলি সামঞ্জস্যতা স্তরের মাধ্যমে নতুন আর্কিটেকচারে কাজ চালিয়ে যায়। তবে, নতুন মডিউলের জন্য সরাসরি TurboModules-এর মাধ্যমে JSI ব্যবহার করার সুপারিশ করা হয়। বিদ্যমান মডিউল স্থানান্তর মডিউলের ব্যবসায়িক যুক্তি পরিবর্তন না করে মিথস্ক্রিয়া প্রোটোকল প্রতিস্থাপন করে।
JSI একটি মৌলিক স্তর যার উপর নতুন React Native আর্কিটেকচারের সমস্ত উপাদান নির্মিত। JSI ছাড়া, Fabric (নতুন রেন্ডারার) বা TurboModules (অপ্টিমাইজড নেটিভ মডিউল) কোনটিই সম্ভব হতো না। JSI সমস্ত স্তরে JS-কে C++-এর সাথে ইন্টারঅ্যাক্ট করার একটি ইউনিফাইড উপায় প্রদান করে।
Fabric হল React Native-এর নতুন রেন্ডারার যা C++ UI উপস্থাপনায় সিনক্রোনাস অ্যাক্সেসের জন্য JSI ব্যবহার করে। পুরানো আর্কিটেকচারে, রেন্ডারিং Bridge-এর মাধ্যমে হতো: JS React এলিমেন্ট তৈরি করত, JSON-এ সিরিয়ালাইজ করত, Bridge-এর মাধ্যমে পাঠাত, নেটিভ পক্ষ ডিসিরিয়ালাইজ করত এবং UI তৈরি করত। Fabric JSI-এর মাধ্যমে সরাসরি JS থেকে C++ শ্যাডো ট্রি অবজেক্ট তৈরি করে, Yoga-এর মাধ্যমে সিনক্রোনাসভাবে লেআউট গণনা করে এবং প্রস্তুত ফ্রেম নেটিভ রেন্ডারারে পাঠায় — একটি সিরিয়ালাইজেশন ছাড়াই।
TurboModules হল React Native নেটিভ মডিউলের বিবর্তন। Bridge-এ মডিউল নিবন্ধন এবং JSON-এর মাধ্যমে এর মেথড কল করার পরিবর্তে, TurboModules লেজি লোডিং এবং সরাসরি আহ্বানের জন্য JSI ব্যবহার করে। যখন JS কোড প্রথমবার একটি মডিউল অ্যাক্সেস করে, JSI একটি হোস্ট অবজেক্ট তৈরি করে — এটি নেটিভ মডিউল লোড করে এবং এর মেথডগুলিকে C++ ফাংশন হিসাবে উপস্থাপন করে। লেজি লোডিং মানে মডিউল প্রথম অ্যাক্সেস পর্যন্ত মেমোরি খরচ করে না — এটি বিশেষত ডজনখানেক নেটিভ মডিউল সহ অ্যাপ্লিকেশনের জন্য গুরুত্বপূর্ণ, যার মধ্যে অনেকগুলি শুধুমাত্র নির্দিষ্ট স্ক্রিনে ব্যবহার করা হয়।
নতুন আর্কিটেকচারে JSI-এর সাথে কাজ করার জন্য Codegen ব্যবহার করা হয় — একটি টুল যা JavaScript স্পেসিফিকেশন থেকে C++ বাইন্ডিং তৈরি করে। ডেভেলপার TypeScript বা Flow-এ নেটিভ মডিউল ইন্টারফেস বর্ণনা করে এবং Codegen JSI-সামঞ্জস্যপূর্ণ হোস্ট অবজেক্ট বাস্তবায়নকারী C++ কোড তৈরি করে। এটি রুটিন কাজ স্বয়ংক্রিয় করে এবং গ্যারান্টি দেয় যে JS এবং C++ পাশের টাইপগুলি সিঙ্ক্রোনাইজ করা আছে।
আসুন দেখি বাস্তবে JSI-এর সাথে কাজ কেমন দেখায়। এই উদাহরণে, আমরা একটি সাধারণ C++ ক্লাস তৈরি করি যা JSI-এর মাধ্যমে JS-এ রপ্তানি করা হয় এবং React Native-এ JavaScript কোড থেকে এর মেথড কল করি।
// Calculator.h — JS থেকে অ্যাক্সেসযোগ্য C++ ক্লাস হেডার
class Calculator {
public:
double add(double a, double b) { return a + b; }
double multiply(double a, double b) { return a * b; }
};
Calculator ক্লাসে দুটি পাটিগণিত মেথড রয়েছে। আমাদের এটি JS থেকে অ্যাক্সেসযোগ্য করতে হবে। এর জন্য, একটি হোস্ট অবজেক্ট তৈরি করা হয় যা Calculator-কে র্যাপ করে এবং JSI-এর মাধ্যমে এর মেথড উপস্থাপন করে।
// CalculatorHostObject.cpp — JSI র্যাপার বাস্তবায়ন
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();
}
};
এই কোডে, get মেথড প্রতিবার কল করা হয় যখন JS অবজেক্টের একটি প্রপার্টি অ্যাক্সেস করে। যদি প্রপার্টির নাম “add” হয়, একটি C++ ফাংশন ফেরত দেওয়া হয় যা JS থেকে দুটি আর্গুমেন্ট নেয় এবং calc.add() কল করে। মান jsi::Value হিসাবে ফেরত দেওয়া হয় — JSI স্বয়ংক্রিয়ভাবে double-কে JS সংখ্যায় রূপান্তর করে।
JS পরিবেশে হোস্ট অবজেক্ট নিবন্ধনের পর, কলটি একটি সাধারণ JS ফাংশনের মতো দেখায়। কোড জেনারেশন পর্যায়ে সমস্ত টাইপ পরীক্ষা করা হয়, যা রানটাইমের সময় টাইপ অমিল ত্রুটি দূর করে।
// JavaScript — JSI-এর মাধ্যমে C++ ক্যালকুলেটর কল করা
import { Calculator } from 'react-native-calculator'
const result = Calculator.add(5, 3)
console.log(result) // 8 — সিনক্রোনাস, বিলম্ব ছাড়া
const product = Calculator.multiply(4, 2.5)
console.log(product) // 10 — তাৎক্ষণিক ফলাফল
লক্ষ্য করুন: ফলাফল অবিলম্বে ফেরত দেওয়া হয়, Promise ছাড়া, await ছাড়া, কলব্যাক ছাড়া। এটি একটি সিনক্রোনাস কল যা Bridge আর্কিটেকচারে অসম্ভব ছিল। দীর্ঘস্থায়ী অপারেশন (ফাইল পড়া, নেটওয়ার্ক অনুরোধ) এর জন্য অ্যাসিনক্রোনাস প্যাটার্ন ব্যবহার করা উচিত — JSI ভারী কাজের জন্য ব্যাকগ্রাউন্ড থ্রেডের প্রয়োজনীয়তা দূর করে না।
বাস্তবে, বেশিরভাগ ডেভেলপার ম্যানুয়ালি JSI হোস্ট অবজেক্ট লেখেন না — এই কাজটি Codegen করে, যা TypeScript স্পেসিফিকেশনের উপর ভিত্তি করে C++ র্যাপার তৈরি করে। তবে, JSI কীভাবে অভ্যন্তরীণভাবে কাজ করে তা বোঝা কার্যকরী পারফরম্যান্স ডিবাগিং এবং জটিল নেটিভ মডিউল তৈরি করার সময় প্রয়োজনীয়, যার জন্য C++ লাইব্রেরি (Skia, FFmpeg, OpenCV)-তে সরাসরি অ্যাক্সেস প্রয়োজন।
প্রায়শই জিজ্ঞাসিত প্রশ্ন
Bridge JSON সিরিয়ালাইজেশন এবং বার্তা সারির মাধ্যমে অ্যাসিনক্রোনাসভাবে কাজ করে — প্রতিটি কল ডেটা রূপান্তরের জন্য 3–10 ms নেয়। JSI সিরিয়ালাইজেশন ছাড়াই C++ অবজেক্টে সিনক্রোনাস সরাসরি অ্যাক্সেস প্রদান করে, লেটেন্সি 0.1–0.5 ms-এ কমিয়ে আনে। JSI কপির পরিবর্তে অবজেক্ট রেফারেন্স পাস করাও সমর্থন করে।
হ্যাঁ, JSI একটি ইউনিফাইড C++ API প্রদান করে যা Hermes (React Native ডিফল্ট), JavaScriptCore (iOS) এবং V8 (Android)-এর জন্য বাস্তবায়িত। ডেভেলপারদের বিভিন্ন ইঞ্জিনের জন্য আলাদা কোড লেখার প্রয়োজন নেই — Fabric এবং TurboModules সব সমর্থিত ইঞ্জিনে একইভাবে কাজ করে।
হ্যাঁ, React Native পশ্চাদগামী সামঞ্জস্য স্তর প্রদান করে। Bridge-এর জন্য লেখা নেটিভ মডিউলগুলি নতুন আর্কিটেকচারে কাজ চালিয়ে যায়। তবে, JSI-এর সুবিধা — লেজি লোডিং এবং সিনক্রোনাস কল — পেতে তাদের TurboModules-এ স্থানান্তর করার সুপারিশ করা হয়।
দৈনন্দিন ডেভেলপমেন্টের জন্য — না। নেটিভ মডিউলের TypeScript স্পেসিফিকেশন Codegen-এর মাধ্যমে স্বয়ংক্রিয়ভাবে C++ বাইন্ডিং-এ কম্পাইল হয়। C++ জ্ঞান শুধুমাত্র কাস্টম C++ লাইব্রেরি তৈরি করার সময় বা রানটাইম স্তরে JSI পারফরম্যান্স ডিবাগ করার সময় প্রয়োজন।
JSI Bridge-এর তিনটি মূল সমস্যা সমাধান করে: JSON সিরিয়ালাইজেশনের কারণে উচ্চ লেটেন্সি, সিনক্রোনাস কলের অভাব এবং জটিল অবজেক্ট রেফারেন্স দ্বারা পাস করতে অক্ষমতা। JSI Java বা Objective-C মধ্যস্থতাকারী ছাড়াই C++ লাইব্রেরি সরাসরি সংহত করার অনুমতি দেয়।
সারাংশ
আমরা একটি মোবাইল অ্যাপ্লিকেশন টার্নকি তৈরি করব
IT Sectr 2017 সাল থেকে স্টার্টআপ এবং ব্যবসার জন্য iOS এবং Android অ্যাপ্লিকেশন তৈরি করে। আমরা আপনাকে পরামর্শ দেব এবং সেরা সমাধান প্রস্তাব করব।
আরও পড়ুন