جزئیات تکنیکی
این مطلب دومین مطلب از مجموعه «تجربه استفاده از React Native در Airbnb» است که ما در آن به بررسی تجربه استفاده از ریاکت نیتیو و آینده اپلیکیشن موبایلی در Airbnb میپردازیم.
ریاکت نیتیو یکی از فریمورکهای جدید و به سرعت در حال پیشرفت است که برای ایجاد اپلیکیشنها به صورت چندسکویی استفاده میشود. بعد از دو سال استفاده حال میتوانیم بگوییم که ریاکت واقعا در راههای مختلفی انقلاب کرده است. در حقیقت ریاکت یک ابزار بسیار مؤثر در تغییر مسیر کلی توسعه بوده و حال میتوانیم از ویژگیهای آن که برای اهداف متفاوتی نوشته شده است استفاده کنیم. با این حال تمام این فواید بدون در نظر گرفتن مشکلات و سختیهایی که در راه وجود دارد نیز بدست نخواهد آمد.
ریاکت نیتیو در چه چیزهایی خوب بود
چند-سکویی
یکی از اصلیترین فواید ریاکت نیتیو این واقعیت بود که کدهای شما به صورت محلی و با المانهای محلی در آندروید و IOS اجرا خواهد شد. بیشتر ویژگیهایی که در React Native استفاده میشود تقریبا ۹۵-۱۰۰٪ کدهای مشترکی را شامل میشود و ۰.۲٪ درصد این فرایند مربوط به فایلهای منحصر به فرد هر سیستم عامل میشود.
سیستم زبان طراحی متحد یا DLS
ما یک زبان طراحی چند-سکویی به نام DLS را توسعه دادیم. در این سیستم برای هر کامپوننت نسخه منحصر به فرد Android, IOS, React Native و ورژن وب را در اختیار داریم. داشتن یک زبان طراحی متحد و یکپارچه به ما این قابلیت را میداد تا بتوانیم ویژگیهای مربوط به چند-سکویی بودن را بنویسیم. به این دلیل که ما صفحات نمایش، نامها و طراحیهای سازگار و همخوانی با همدیگر داشتیم. با این حال ما همچنان قابلیت این را داشتیم که براساس یک پلتفرم خاص کامپوننت یا ویژگی را طراحی و توسعه بدهیم. برای مثال، ما از Toolbar محلی مربوط به آندروید و از UINavigationBar مربوط به IOS استفاده کردیم.
ما تصمیم گرفتیم که بجای استفاده صرف از کامپوننتهای محلی آنها را بازنویسی کنیم. انجام چنین کاری به ما قابلیت انعطافپذیرتر و قابل اعتمادتری برای نوشتن المانها و APIها برای هر پلتفرم را میداد. با این حال چنین موضوعی باعث بوجود آمدن شکافی نیز در بین پلتفرمهای مختلفی که با نسخههای متفاوتی از یک کامپوننت نوشته شده بودند میشد.
ریاکت
یک دلیل برای اینکه چرا ریاکت یکی از پرطرفدارترین وب فریمورک های دنیا است وجود دارد. ریاکت ساده و در عین حال قدرتمند است، همچنین قابلیت این را دارد که اپلیکیشنهایی در مقیاس عظیم را با آن نوشت. برخی از مواردی که ما منحصرا دوستشان داریم عبارت هستند از:
- کامپوننتها : کامپوننتهای ریاکت نگرانی از تعیین درست وضعیتها را از شما دور میکند. این یکی از موضوعات مهم در ایفای نقش ریاکت در رابطه با موضوع مقیاسپذیری است.
- چرخه حیات ساده شده : آندروید و آياواس چرخه حیات یا Lifecycle پیچیدهای دارند.کامپوننتهای ریاکت تا حد بسیاری این مشکل را حل میکنند و همین باعث میشود که یادگیری ریاکت نیتیو بسیار سادهتر از آندروید و آیاواس باشد.
- اظهاری : طبیعت اظهاری ریاکت به ما این اجازه را میدهد که بتوانیم رابط کاربریمان را با وضعیت زیرین همگام سازیم.
سرعت جهش
در زمان توسعه اپلیکیشن با استفاده از ریاکت نیتیو ما این قابلیت را داشتیم که از موضوع hot reloading برای تست کردن تغییراتمان در آندروید و IOS استفاده کنیم. حتی با این حال که ایجاد کارایی مطلوب یکی از اولویتهای ما برای اپلیکیشنهای محلی است اما سرعت جهش این موضوع هیچوقت به میزانی نرسید که ما با ریاکت نیتیو به آن رسیدیم.
در نظر گرفتن زیرساختها
ما ادغامسازیهای وسیعی را در زیرساخت محلیمان توسعه دادیم. تمام قسمتهای اصلی مانند networking، i18n، experimentation و بسیاری از چیزهای دیگر در یک API محلی مربوط به ریاکت نیتیو قرار دارد. این موارد پیچیدهترین بخشهای کاری بودند. به این دلیل که ما قصد داشتیم تا APIهای مربوط به هر یک از سیستمعاملهای Android و IOS را در یک موجودیت یکپارچه ریاکت قرار دهیم. درحالیکه ایجاد این پلها مشکلاتی مانند بروزرسانی لازم دارد و نیاز به انجام کارهای تکراری دیگری است، بنابراین داشتن یک تیم زیرساخت تولید محصول را بسیار سادهتر میکند.
بدون در نظر گرفتن زیرساختها، ریاکت نیتیو ممکن است تیم و تجربه کاربری شما را به حداقل میزان برساند. به عنوان یک نتیجه ما باور داریم که استفاده کردن از ریاکت نیتیو و ادغام کردن آن با یک اپلیکیشن واقعی و موجود کار چندان سادهای نیست.
کارایی
یکی از بزرگترین نگرانیها در رابطه با ریاکت نیتیو کارایی و Performance آن است. با این حال در یک مثال عملی این موضوع واقعا یکی از مشکلات است. معمولا فکر و ایده مربوط به موضوع کارایی از یک دید مشاهده میشود. به عنوان مثال معمول گفته میشود که موتور جاوااسکریپت از جاوا کُندتر است. اما ادغام کردن قسمت Business Logic و Layout با قسمت اصلی میتواند تاثیر بسیار خوبی روی کارایی اپلیکیشن داشته باشد.
در مسئله ریاکت نیتیو و در تجربیات ما استفاده درست از مواردی مانند shouldComponentUpdate، removeClippedSubviews و Redux میتواند تاثیر مثبت بسیاری را روی کارایی بگذارد.
Redux
ما از Redux برای مدیریت وضعیت استفاده میکنیم. استفاده از این مورد باعث میشود که روند همگامسازی رابط کاربری با وضعیتهای مختلف در اسکرینهای متفاوت آسانتر شود و به اشتراک گذاری دادهها روند سادهتری داشته باشند. در هر حال Redux به دلیل داشتن سینتکس خاص و روند یادگیری سخت کمی بدنام شده است. برخی سازندهها برای برخی از قالبهای معروف وجود دارند اما با این حال نیز بخشی از منبع اصلی برای سردرگمی در کار با ریاکت نیتیو به حساب میآید.
پشتیبانی از Native
به این دلیل که در ریاکت نیتیو همه کامپوننتها میتوانند به کدهای نیتیو تبدیل شوند، ما در نهایت توانستیم بسیاری از چیزهایی که فکر میکردیم ایجاد آنها با ریاکت ممکن نیست را بسازیم:
- Shared element transitions: ما یک کامپوننت با نام <SharedElement> را ایجاد کردیم که براساس کدهای محلی مربوط به Android و IOS کار میکند. این مورد حتی بین اسکرینهای محلی و ریاکت نیتیو نیز کار میکند.
- Lottie: قابلیت کار کردن با Lottie از طریق کتابخانههای مربوط به آندروید و IOS موجود است.
- Native networking stack: ریاکت نیتیو در حال حاضر از پشته شبکهای محلی ما استفاده میکند و این موضوع در هر دو پلتفرم پیادهسازی شده است.
- Other core infra: درست شبیه به موضوع شبکهسازی، بقیه موارد مانند i18n، experimentation و… نیز به همین شکل پیادهسازی شدهاند.
آنالیزهای ایستا
مطمئنا تاریخ استفاده از eslint را در حرفه وب شنیدهاید. ما هم در اینجا از آن استفاده می کنیم. حال در تیم توسعه زیرساخت ما به صورت عمده از ابزارهایی نیز مانند Prettier استفاده میکنیم.
اما در کنار این موارد یک سیستم آنالیز را نیز در اختیار داشتیم که زمان رندر و کارایی اپلیکیشن را بررسی میکرد تا مشکلات و مسائل را بهتر به ما نشان دهد.
به این دلیل که زیرساخت اصلی شرکت ما قبل از ایجاد ریاکت نیتیو توسعه داده شده بود و عملا تکنولوژی کوچکتری نیز است، حال توانسته به ما در ایجاد ایدههای جدیدمان کمک بسیار بکند.
انیمیشنها
خوشبختانه با وجود کتابخانه React Native Animated ما قابلیت این را داشتیم که به انیمیشنها و روشهای مختلف متحرک سازی دسترسی داشته باشید.
JS/React متن باز
به این دلیل که ریاکت نیتیو کاملا براساس ریاکت و جاوااسکریپت ساخته شده بود ما قابلیت آن را داشتیم که به پروژههای بسیاری از آن دسترسی داشته باشیم.
فلکسباکس
ریاکت نیتیو لایهبندیها را با استفاده از Yoga مدیریت می کند. Yoga یک کتابخانه سی است که محاسبات لایهبندی با استفاده از APIهای مربوط به فلکسباکس را محاسبه میکند.
همکاری با وب
در اواخر کشفیاتمان در رابطه با ریاکت نیتیو ما شروع به ایجاد اپلیکیشن برای وب، آیاواس و آندروید در یک زمان کردیم. در این مسیر راههای بسیار زیادی را پیدا کردیم که در آنها بدون در نظر گرفتن هیچگونه تغییراتی میتوانستیم کدها را در بین پلتفرمهای مختلف به اشتراک بگذاریم.
ریاکت نیتیو در چه چیزهایی خوب عمل نمیکند
نارسایی ریاکت نیتیو
ریاکت نیتیو به اندازه آندروید و IOS کامل نیست. این تکنولوژی جدیدتر و به سرعت در حال حرکت است. در حالیکه ریاکت نیتیو در بیشتر مواقع میتواند به خوبی عمل کند اما زمینههایی نیز وجود دارد که نارسایی ریاکت نیتیو در آنجاها کاملا به چشم دیده میشود. متاسفانه پیش بینی چنین موقعیتهایی معمولا سخت است و تا زمانی که با آن ها همراه نشوید نمیتوانید شناساییشان بکنید.
نگهداری از یک Fork مربوط به ریاکت نیتیو
به دلیل نارسا بودن ریاکت نیتیو گاهی اوقات نیاز است که کدهای آن را تغییر دهیم. در این زمینه ما یک فورک از ریاکت نیتیو را در اختیار داریم که بعد از دو سال ۵۰ کامیت را به آن اضافه کردهایم. پروسه توسعه و ارتقا دادن به ریاکت نیتیو به شدت سخت و دشوار است.
ابزار جاوااسکریپت
جاوااسکریپت یک زبان غیر تایپی است. به همین دلیل استفاده از آن برای توسعهدهندگان موبایلی که از یک زبان تایپی استفاده کردهاند ممکن است سخت باشد. البته تایپ اسکریپت تا حد بسیاری میتواند به ما در این زمینه کمک بکند.
بازسازی
یکی از مشکلاتی که همراه با غیر تایپی بودن جاوااسکریپت میآید همین موضوع بازسازی کردن است که روند را بسیار سخت و پر از خطا میکند. بازنویسی نام خاصیتها، مخصوصا مواردی مانند onCick در واقع شبیه به یک کابوس است.
ناسازگاری در JavascriptCore
یکی از جنبههای مهم در رابطه با ریاکت نیتیو که باید بدانید این است که ریاکت نیتیو روی JavascriptCore Env اجرا میشود. با در نظر گرفتن چنین موضوعی مسائل زیر بوجود میآيند:
IOS همراه با یک JavascriptCore مربوط به خود ارائه میشود. این بدان معناست که تقریبا با ریاکت سازگار است و مشکلات زیادی برای ما به وجود نمیآورد.
آندروید JavascriptCore منحصر به فرد خود را ندارد، بنابراین ریاکت نیتیو JavascriptCore خود را به اپلیکیشن باندل میکند. در هر حال این روند کمی سنتی است به این دلیل که در بروزرسانیها مجبوریم همه چیز را بروزرسانی کنیم.
در زمان دیباگ کردن پروژه ریاکت نیتیو ما از ابزارهای توسعه کروم استفاده میکنیم. به همین دلیل نیز تمام جاوااسکریپت براساس موتور V8 ارائه میشود. این موضوع در ۹۹.۹ درصد حالا خوب است اما یک نمونه وجود دارد که ما با آن مشکلات سازگاری را داریم. برای مثال toLocaleString یکی از آن مسائلی است که ما در نسخههای IOS و آندروید با آن مشکل پیدا خواهیم کرد.
بدون در نظر گرفتن چنین جزئیات دقیق و تکنیکی ممکن است در زمان دیباگ کردن این موضوعات برایتان بسیار سخت و زجرآور باشد.
کتابخانههای متنباز ریاکت نیتیو
یادگیری یک پلتفرم معمولا سخت و زمانبر است. بیشتر مردم تنها یک یا دو پلتفرم را به خوبی میشناسند. کتابخانههای ریاکت نیتیو پلهای محلی برای maps، video و… را ارائه میدهند. برای یادگیری و استفاده کامل از تمام این موارد شما نیاز دارید که درک خوبی از هر سه پلتفرم (آندروید، آياواس و ریاکت نیتیو) داشته باشید. این در حالیست که عموم مردم تنها در رابطه با دو مورد از این موارد دانش کافی دارند. این موضوع باعث بوجود آمدن عدم سازگاری و باگهای غیرمنتظره میشود.
زیرساخت موازی و ویژگی کاری
ما سالهای بسیاری از یک زیرساخت کاملا محلی برای آندروید و آیاواس استفاده کردیم. در هر حال، در ریاکت نیتیو، ما با دست خالی شروع کردیم و مجبور شدیم برای تمام زیرساختهای موجود پلهایی را ایجاد کنیم. این بدان معناست که مهندسین باید کاراییهایی را ایجاد میکردند که عملا در بعضی از حالات وجود نداشته است. در چنین مرحلهای بعضی از آنها باید با پلتفرمی کار بکنند که با آن آشنایی کاملی ندارند.
مانیتورینگ کرَشها
ما از Bugsnag برای گزارش خطاها و مشکلات داخل آندروید و IOS استفاده میکنیم. درحالیکه ما میتوانستیم به صورت کلی از Bugsnag در هر دو پلتفرم استفاده کنیم اما این حالت پایداری کمتری به ما میداد و زحمت بسیاری را میطلبید. به این دلیل که ریاکت نیتیو نسبتا جدید است و در صنعت تقریبا کمتر استفاده شده، ما نیاز داریم که مقدار قابل توجهی از زیرساختها را مانند uploading source maps in-house و قابلیت فیلتر کرشها در Bugsnags را پیادهسازی کنیم.
پلهای محلی
ریاکت نیتیو یک bridge API برای ارتباط برقرار کردن بین المانهای محلی و ریاکت نیتیو در اختیار دارد. در حالیکه درست مانند چیزی که انتظار داریم کار میکند اما نوشتن چنین مواردی واقعا سخت است. برای انجام چنین کاری ابتدا نیاز است که محیط توسعه هر سه پلتفرم به صورت کامل پیادهسازی شده باشد. البته این موضوع را نیز باید در نظر گرفت که مشکلات تایپی با جاوااسکریپت همراه است. برای مثال ممکن است برخی اوقات مقداری که به صورت عدد صحیح ارسال میشود با رشته دریافت شود. این مشکلی است که تا زمان ایجاد و گذر از پل خود را نشان نمیدهد. به همین دلیل برخی اوقات جاوا و یا IOS با کرشها و مشکلاتی همراه میشود. در حال حاضر ما به تایپ اسکریپت برای حل این مشکل فکر میکنیم.
زمان مقداردهی اولیه
قبل از اینکه ریاکت نیتیو بتواند برای اولین بار رندر شود، شما باید runtime آن را مقداردهی کنید. متاسفانه این پروسه برای اپلیکیشنی در اندازه اپلیکیشن ما حتی روی موبایلهایی با مشخصات سختافزاری خوب چند ثانیه طول میکشد.
اندازه اپلیکیشن
ریاکت نیتیو یکی از عوامل تاثیرگذار روی اندازه اپلیکیشنها به حساب میآید. در آندروید، اندازه کامل ریاکت نیتیو همراه با تمام موارد الزامی آن ۸مگابیت است. با در نظر گرفتن نسخههای x86 و arm حجمی نزدیک به ۱۲مگابیت است.
۶۴-بیت
ما هنوز نمیتوانیم روی APK ۶۴ بیتی در آندروید کار بکنیم. برای اطلاع بیشتر در رابطه با این موضوع این لینک را مطالعه کنید.
Gestures
معمولا برای نوشتن اپلیکیشنهایی که مسائل تاچ اسکرین پیچیدهای میطلبند از استفاده کردن ریاکت نیتیو خودداری میکنیم. به این دلیل که ساب سیستم مربوط به سیستم عاملهای آندروید و آیاواس متفاوت هستند و این موضوع برای ریاکت نیتیو چالش برانگیز است.
لیستهای طولانی
ریاکت نیتیو در این زمینه پیشرفتهای بسیار خوبی داشته، این پیشرفتها تا حدی مربوط به کتابخانههایی مانند FlatList میشود. در هر حال این موارد حتی کارایی نزدیک به موارد مشابه در آندروید و آياواس را نمیدهند. غلبه کردن بر بسیاری از این محدودیتها معمولا سخت است. دادههای تطبیقپذیر توانایی دسترسی داشتن به صورت همگام را ندارند. به همین دلیل در زمانی که به صورت غیرهمزمان رندر میشوند توانایی مشاهده سریع را خواهند داشت.
ارتقا دادن ریاکت نیتیو
اگرچه بیشتر بروزرسانیها و ارتقاهای ریاکت نیتیو بسیار ناچیز هستند، اما در این مسیر راهحل هایی نیز ارائه شده است. این مشکلات برخی اوقات برای پیادهسازی ریاکت نیتیو براساس نسخههای غیرپایدار ریاکت اتفاق میافتاد.
قابلیت دسترسیپذیری
در سال ۲۰۱۷ ما بررسی کاملی را روی دسترسیپذیری اپلیکیشن انجام دادیم. این کار را در این جهت انجام دادیم تا مطمئن شویم همه مردم حتی با وجود ناتوانیهایی با اپلیکیشن کار بکنند. در هر حال مشکلات و مسائل بسیاری با موضوع دسترسیپذیری در APIهای ریاکت نیتیو وجود داشت. برای اینکه بتوانیم دسترسیپذیری بهتری را ارائه دهیم ما تصمیم گرفتیم که روی فورک مربوط به خودمان کار کنیم.
خرابیهای ناراحت کننده
در استفاده از ریاکت نیتیو نیاز است تا برخی از کرَشهایی که سر راهمان است را حل نماییم. برای مثال، در حال حاضر ما با این مشکل در @ReactProp همراه هستیم. برخی مشکلات دیگر نیز وجود دارد که معمولا در زمان کار با ریاکت متوجه آن خواهید بود.
پردازشهای SavedInstanceState در آندروید
آندروید معمولا به صورت دورهای پردازشهای مربوط به پس زمینهاش را پاک میکند اما در این زمان به آنها شانسی نیز برای ذخیره وضعیتها به صورت همگام را در باندلها بدهید. در هر حال ریاکت نیتیو تمام وضعیتها تنها در یک رشته جاوااسکریپتی قابل دسترسی است. بنابراین چنین کاری به صورت همگام انجام شدنی نیست. حتی اگر مشکل به این مسئله نیز مربوط نمیشد، Redux سازگاری با این وضعیت نداشت.
این مطلب دومین مطلب از مجموعه «تجربه استفاده از React Native در Airbnb» است که ما در آن به بررسی تجربه استفاده از ریاکت نیتیو و آینده اپلیکیشن موبایلی در Airbnb میپردازیم.
دیدگاه و پرسش
در حال دریافت نظرات از سرور، لطفا منتظر بمانید
در حال دریافت نظرات از سرور، لطفا منتظر بمانید