برنامه نویسی

راهنمای ماژول های توربو در React Native

به‌عنوان یک توسعه‌دهنده React Native، من از انعطاف‌پذیری ناشی از عملکرد متقابل پلتفرم چارچوب قدردانی می‌کنم. اما، لحظاتی وجود دارد که من نیاز به دسترسی به عملکرد بومی دارم. وارد Turbo Modules شوید، درب جادویی React Native به دنیای بومی.

در این مقاله من با پوشش ماژول‌های توربو و نیاز اساسی که منجر به ایجاد آن‌ها شد، شروع خواهم کرد. از آنجا، من شما را از طریق یک مثال گام به گام راهنمایی می‌کنم که در آن نحوه ایجاد یک ماژول توربو سفارشی و ادغام آن در برنامه React Native خود را آموزش می‌دهم و امکان دسترسی مستقیم به API Native Android را فراهم می‌کند. این برنامه سپس می تواند بر روی هر دستگاه Android یا Fire OS اجرا شود، همانطور که در دمو زیر نشان داده شده است:

برنامه نمایشی Turbo Module در تبلت آمازون فایر

TLDR: مخزن Github را در اینجا بررسی کنید.

چرا ماژول های توربو مهم هستند – غلبه بر محدودیت های ماژول های بومی

پیش از این هنگام کار با React Native، ارتباط بین لایه‌های Native و JavaScript برنامه‌ها از طریق پل جاوا اسکریپت – که به عنوان Native Modules نیز شناخته می‌شود، انجام می‌شد. با این حال، این رویکرد دارای تعدادی اشکال بود:

  • پل به صورت ناهمزمان کار می کرد، به این معنی که چندین تماس را به لایه اصلی ارسال می کرد و آنها را در فواصل از پیش تعیین شده فراخوانی می کرد.
  • داده‌هایی که از پل عبور می‌کردند باید در سمت اصلی سریال‌سازی و سریال‌زدایی می‌شدند که سربار و تأخیر را معرفی می‌کرد.
  • پل فاقد نوع ایمنی بود. هر داده ای را می توان بدون اجرای دقیق از طریق آن منتقل کرد و آن را به لایه اصلی واگذار کرد تا داده ها را به طور مناسب مدیریت و پردازش کند.
  • در طول راه اندازی برنامه، تمام ماژول های بومی باید در حافظه بارگذاری می شدند که باعث تاخیر در راه اندازی برنامه برای کاربران می شد.

برای مقابله با این مشکلات، سازندگان React Native معرفی کردند:

Codegen، Turbo Modules و Fabric که معماری جدید React را تشکیل می دهند.

توضیحات تصویر

ماژول‌های توربو تکرار بعدی ماژول‌های بومی هستند که به مشکلات ناهمزمان و بارگذاری توسط ماژول‌های بارگذاری تنبل رسیدگی می‌کنند و امکان راه‌اندازی سریع‌تر برنامه را فراهم می‌کنند. ماژول‌های توربو عملکرد برنامه شما را بهبود می‌بخشند، زیرا با دور زدن پل جاوا اسکریپت و ارتباط مستقیم با کد بومی، سربار ارتباط بین جاوا اسکریپت و کد بومی را کاهش می‌دهند.

کدجن مشکل ایمنی نوع را با ایجاد یک رابط جاوا اسکریپت در زمان ساخت برطرف می کند. این رابط ها تضمین می کنند که کد بومی با داده های ارسال شده از لایه جاوا اسکریپت همگام می ماند. علاوه بر این، Codegen ایجاد اتصالات JSI را تسهیل می کند، که تعامل موثر و مستقیم بین جاوا اسکریپت و کد بومی را بدون نیاز به پل امکان پذیر می کند. استفاده از اتصالات JSI به برنامه‌های React Native اجازه می‌دهد تا به ارتباطات سریع‌تر و بهینه‌تر بین لایه‌های بومی و جاوا اسکریپت دست یابند.

علاوه بر این، Fabric سیستم رندر جدیدی برای React Native است که از قابلیت‌های Turbo Modules و Codegen بهره می‌برد. این سه مؤلفه با هم، ستون‌های معماری جدید در React Native را تشکیل می‌دهند که عملکرد بهبود یافته، ایمنی نوع بهبود یافته و قابلیت همکاری ساده بین کد بومی و جاوا اسکریپت را ارائه می‌دهند.

وای، پیچیده به نظر می رسد! 🤯 بنابراین ممکن است از خود بپرسید:

در چه سناریوهایی به ماژول توربو نیاز دارم؟

  1. دسترسی به API های دستگاه: ماژول‌های توربو می‌توانند به شما اجازه دسترسی مستقیم به API‌های دستگاهی را بدهند که از طریق ماژول‌های استاندارد جاوا اسکریپت در معرض نمایش نیستند. این به شما امکان می دهد با قابلیت های خاص دستگاه مانند دسترسی به حسگرها، بلوتوث یا سایر ویژگی های سخت افزاری یکپارچه شوید. در حالی که در برخی موارد می توانید از ماژول های استاندارد جاوا اسکریپت استفاده کنید، ممکن است عملکرد بهینه نباشد و ممکن است به تمام ویژگی های پیشرفته ارائه شده توسط API های بومی دسترسی نداشته باشید. ماژول های توربو دسترسی به عملکرد کامل بومی را ایجاد می کنند.
  2. اجزای UI بومی: ماژول‌های توربو را می‌توان برای ایجاد مؤلفه‌های UI بومی سفارشی استفاده کرد که در مقایسه با همتایان مبتنی بر جاوا اسکریپت، تجربه کاربری یکپارچه‌تر و کارآمدتری را ارائه می‌دهند.
  3. وظایف فشرده CPU: اگر برنامه شما کارهای فشرده CPU مانند پردازش تصویر، رمزگذاری صوتی/تصویری یا محاسبات پیچیده را انجام می‌دهد، استفاده از یک ماژول توربو می‌تواند به تخلیه این وظایف به کد اصلی، بهره‌گیری از قدرت محاسباتی دستگاه و بهینه‌سازی عملکرد کمک کند.

مراحل ایجاد یک ماژول توربو برای برنامه شما

بیایید به نحوه اضافه کردن یک ماژول توربو سفارشی به یک برنامه React Native که معماری جدید را فعال کرده است، بپردازیم. مثال Turbo Module که ما طراحی خواهیم کرد، شماره مدل یک دستگاه اندرویدی را برای برنامه ما به نمایش در می آورد. سپس می‌توانیم برنامه React Native خود را بر روی هر دستگاه Android از جمله دستگاه‌های Amazon Fire اجرا کنیم.

پیش نیازها

نکته: هر نسخه قدیمی را حذف کنید react-native-cli package، زیرا ممکن است باعث ایجاد مشکلات غیرمنتظره در ساخت شود. می توانید از دستور استفاده کنید npm uninstall -g react-native-cli @react-native-community/cli

مرحله 1: یک برنامه جدید ایجاد کنید و پوشه های Turbo Module را راه اندازی کنید

  • یک پوشه جدید به نام TurboModuleDemo ایجاد کنید و در آن یک برنامه جدید به نام DeviceName ایجاد کنید
npx react-native@latest init DeviceName
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

نکته: برای جدا نگه داشتن ماژول توربو از برنامه، ایده خوبی است که ماژول را جدا از برنامه تعریف کنید و بعداً آن را به عنوان یک وابستگی به برنامه خود اضافه کنید. این به شما امکان می دهد در صورت نیاز به راحتی آن را به طور جداگانه آزاد کنید.

  • در داخل TurboModuleDemo، یک پوشه به نام ایجاد کنید RTNDeviceName. RTN مخفف “React Native” است و یک پیشوند توصیه شده برای ماژول های React Native است.
  • در داخل RTNDeviceName، دو زیر پوشه ایجاد کنید: js و android.

ساختار پوشه شما باید به شکل زیر باشد:

TurboModulesDemo
├── DeviceName
└── RTNDeviceName
    ├── android
    └── js
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

مرحله 2: مشخصات جاوا اسکریپت

همانطور که گفته شد، New Architecture به رابط های مشخص نیاز دارد، بنابراین برای این نسخه ی نمایشی از TypeScript استفاده خواهیم کرد. کدجن سپس از این مشخصات برای تولید کد در زبان‌هایی با تایپ قوی (C++، Objective-C++، Java) استفاده می‌کند.

  • در داخل js پوشه، یک فایل به نام ایجاد کنید NativeGetDeviceName.ts. Codegen فقط به دنبال فایل‌هایی می‌گردد که با الگوی Native{MODULE_NAME} مطابقت دارند .ts، یا .tsx افزونه.
  • کد زیر را در فایل کپی کنید:

NativeGetDeviceName.ts

import type { TurboModule } from "react-native/Libraries/TurboModule/RCTExport";
import { TurboModuleRegistry } from "react-native";

export interface Spec extends TurboModule {
  getDeviceModel(): Promise<string>;
}

export default TurboModuleRegistry.get<Spec>("RTNDeviceName") as Spec | null;
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

بیایید به کد نگاه کنیم. اول واردات است: نوع TurboModule رابط پایه را برای همه ماژول‌های توربو تعریف می‌کند و ماژول جاوا اسکریپت TurboModuleRegistry شامل توابعی برای بارگذاری ماژول‌های توربو است.

بخش دوم فایل شامل مشخصات رابط برای ماژول توربو است. در این مورد، رابط کاربری را تعریف می کند getDeviceModel تابع، که وعده ای را برمی گرداند که به یک رشته حل می شود. این نوع رابط باید Spec برای یک ماژول توربو نامیده شود.

در نهایت استناد می کنیم TurboModuleRegistry.get، نام ماژول را ارسال کنید، که در صورت موجود بودن، ماژول بومی توربو بارگیری می شود.

مرحله 3: اضافه کردن تنظیمات

در مرحله بعد، باید تنظیماتی را برای اجرای Codegen اضافه کنید. در ریشه RTNDeviceName پوشه

  • a اضافه کنید package.jsonفایل با محتوای زیر:

package.json

{
  "name": "rtn-device",
  "version": "0.0.1",
  "description": "Get device name with Turbo Modules",
  "react-native": "js/index",
  "source": "js/index",
  "files": [
    "js",
    "android",
    "!android/build"
  ],
  "keywords": [
    "react-native",
    "android"
  ],
  "license": "MIT",
  "devDependencies": {},
  "peerDependencies": {
    "react": "*",
    "react-native": "*"
  },
  "codegenConfig": {
    "name": "RTNDeviceSpec",
    "type": "modules",
    "jsSrcsDir": "js",
    "android": {
      "javaPackageName": "com.rtndevice"
    }
  }
}
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

Yarn از این فایل هنگام نصب ماژول شما استفاده می کند. همچنین شامل پیکربندی Codegen است – مشخص شده توسط codegenConfig رشته.

  • بعد، a ایجاد کنید build.gradle فایل در پوشه اندروید با محتویات زیر:

build.gradle

buildscript {
  ext.safeExtGet = {prop, fallback ->
    rootProject.ext.has(prop) ? rootProject.ext.get(prop) : fallback
  }
  repositories {
    google()
    gradlePluginPortal()
  }
  dependencies {
    classpath("com.android.tools.build:gradle:7.3.1")
    classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:1.7.22")
  }
}

apply plugin: 'com.android.library'
apply plugin: 'com.facebook.react'
apply plugin: 'org.jetbrains.kotlin.android'

android {
  compileSdkVersion safeExtGet('compileSdkVersion', 33)
  namespace "com.rtndevice"
}

repositories {
  mavenCentral()
  google()
}

dependencies {
  implementation 'com.facebook.react:react-native'
}
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

این مرحله یک کلاس ایجاد می کند که نامیده می شود DevicePackage، که گسترش می دهد TurboReactPackage رابط. این کلاس به عنوان پل ارتباطی بین Turbo Module و اپلیکیشن React Native عمل می کند. جالب اینجاست که لزوماً مجبور نیستید کلاس بسته را به طور کامل پیاده سازی کنید. حتی یک پیاده سازی خالی برای برنامه کافی است تا ماژول توربو را به عنوان یک وابستگی React Native بشناسد و سعی کند کد داربست لازم را تولید کند.

React Native بر روی DevicePackage رابط برای تعیین اینکه کدام کلاس های بومی باید برای ViewManager و Native Modules صادر شده توسط کتابخانه استفاده شوند. با گسترش TurboReactPackage رابط، اطمینان حاصل می کنید که Turbo Module به درستی در معماری برنامه React Native ادغام شده است.

این به این معنی است که حتی اگر کلاس بسته خالی یا فاقد پیاده‌سازی به نظر برسد، برنامه React Native همچنان ماژول توربو را شناسایی و پردازش می‌کند و تلاش می‌کند کد مورد نیاز را برای کاربردی کردن آن تولید کند.

  • یک پوشه به نام ایجاد کنید rtndevice زیر: android/src/main/java/com. در داخل پوشه، a ایجاد کنید DevicePackage.kt فایل.

DevicePackage.kt

package com.rtndevice;

import com.facebook.react.TurboReactPackage
import com.facebook.react.bridge.NativeModule
import com.facebook.react.bridge.ReactApplicationContext
import com.facebook.react.module.model.ReacTurboModuleoduleInfoProvider

class DevicePackage : TurboReactPackage() {
  override fun getModule(name: String?, reactContext: ReactApplicationContext): NativeModule? = null

  override fun getReactModuleInfoProvider(): ReactModuleInfoProvider? = null
}
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

در پایان این مراحل، پوشه اندروید باید به شکل زیر باشد:

android
├── build.gradle
└── src
    └── main
        └── java
            └── com
                └── rtndevice
                    └── DevicePackage.kt
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

مرحله 4: اضافه کردن کد بومی

برای آخرین مرحله در ایجاد ماژول توربو، باید مقداری کد بومی بنویسید تا سمت جاوا اسکریپت را به پلتفرم های اصلی متصل کنید. برای تولید کد برای اندروید، باید Codegen را فراخوانی کنید.

  • از DeviceName اجرای پوشه پروژه:
yarn add ../RTNDeviceName
cd android
./gradlew generateCodegenArtifactsFromSchema
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

نکته: با نگاه کردن به زیر می توانید تأیید کنید که کد داربست تولید شده است: DeviceName/node_modules/rtn-device/android/build/generated/source/codegen

نکته: باز کن android/gradle.properties فایل را در برنامه خود (DeviceName) قرار دهید و مطمئن شوید newArchEnabled دارایی درست است

کد اصلی برای سمت Android یک ماژول توربو از شما می خواهد که یک DeviceModule.kt ایجاد کنید که ماژول را پیاده سازی می کند.

  • در rtndevice پوشه ایجاد یک DeviceModule.kt فایل:
android
├── build.gradle
└── src
    └── main
        └── java
            └── com
                └── rtndevice
                    ├── DeviceModule.kt
                    └── DevicePackage.kt

وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

  • کد زیر را به the اضافه کنید DeviceModule.kt فایل:

DeviceModule.kt

package com.rtndevice
import com.facebook.react.bridge.Promise
import com.facebook.react.bridge.ReactApplicationContext
import com.rtndevice.NativeGetDeviceNameSpec
import android.os.Build

class DeviceModule(reactContext: ReactApplicationContext) : NativeGetDeviceNameSpec(reactContext) {

  override fun getName() = NAME

  override fun getDeviceModel(promise: Promise) {
    val manufacturer: String = Build.MANUFACTURER
    val model: String = Build.MODEL
    promise.resolve(manufacturer + model)
  }

  companion object {
    const val NAME = "RTNDeviceName"
  }
}
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

این کلاس پیاده سازی می کند DeviceModule که گسترش می دهد NativeGetDeviceNameSpec رابطی که توسط کدژن از فایل مشخصات NativeGetDeviceName TypeScript ایجاد شده است. همچنین کلاسی است که شامل ماست getDeviceModel تابع، که یک وعده را با مدل دستگاه به عنوان یک رشته برمی گرداند.

package com.rtndevice;

import com.facebook.react.TurboReactPackage
import com.facebook.react.bridge.NativeModule
import com.facebook.react.bridge.ReactApplicationContext
import com.facebook.react.module.model.ReactModuleInfoProvider
import com.facebook.react.module.model.ReactModuleInfo

class DevicePackage : TurboReactPackage() {
    override fun getModule(name: String?, reactContext: ReactApplicationContext): NativeModule? =
       if (name == DeviceModule.NAME) {
        DeviceModule(reactContext)
       } else {
         null
       }

     override fun getReactModuleInfoProvider() = ReactModuleInfoProvider {
       mapOf(
         DeviceModule.NAME to ReactModuleInfo(
           DeviceModule.NAME,
           DeviceModule.NAME,
           false, // canOverrideExistingModule
           false, // needsEagerInit
           true, // hasConstants
           false, // isCxxModule
           true // isTurboModule
         )
       )
     }
}
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

مرحله 5: ماژول توربو را به برنامه خود اضافه کنید

  • برای افزودن Turbo Module به برنامه خود، از پوشه برنامه DeviceName خود، دوباره اجرا کنید:
yarn add ../RTNDeviceName
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

نکته: برای اطمینان از اینکه تغییرات TurboModule شما در برنامه شما منعکس می شود، برنامه خود را حذف کنید node_modules قبل از اجرای نخ اضافه کنید.

اکنون می توانید از ماژول توربو خود برای استفاده از آن استفاده کنید getDeviceName عملکرد در برنامه شما!

  • در شما App.tsx با … تماس بگیر getDeviceModel روش:

App.tsx

import React from 'react';
import {useState} from 'react';
import {SafeAreaView, StatusBar, Text, Button} from 'react-native';
import RTNDeviceName from 'rtn-device/js/NativeGetDeviceName';

const App: () => JSX.Element = () => {
  const [result, setResult] = useState<string | null>(null);

  return (
    <SafeAreaView>
      <StatusBar barStyle={'dark-content'} />
      <Text style={{marginLeft: 20, marginTop: 20}}>
        {result ?? 'Whats my device?'}
      </Text>
      <Button
        title="Compute"
        onPress={async () => {
          const value = await RTNDeviceName?.getDeviceModel();
          setResult(value ?? null);
        }}
      />
    </SafeAreaView>
  );
};
export default App;
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

با دویدن، ماژول توربو خود را در عمل بررسی کنید npm run android در هر دستگاه اندرویدی از جمله دستگاه های سیستم عامل آمازون Fire:

برنامه نمایشی Turbo Module در تبلت آمازون فایر

تبریک برای اجرای موفقیت آمیز یک ماژول ساده توربو در یک برنامه! امیدواریم با این مقاله و کد نمونه اکنون درک بهتری برای نحوه ادغام ماژول های توربو در پروژه های خود داشته باشید.

در نظرات به من اطلاع دهید که ماژول توربو را برای چه چیزی ایجاد می کنید!

📣 من را در anisha.dev دنبال کنید
📺 در کانال یوتیوب AmazonAppstoreDevelopers ما مشترک شوید
📧 برای خبرنامه توسعه دهندگان آمازون ثبت نام کنید

نوشته های مشابه

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *

دکمه بازگشت به بالا