Airbnb-da Native reaktsiyasi: Texnologiya

Texnik tafsilotlar

Bu bloglardagi ikkinchi xabar, biz React Native bilan tajribamizni va Airbnb-da mobil uchun keyingi narsalar haqida.

React Native o'zi - bu nisbatan yangi va tezkor harakatlanadigan platforma, Android, iOS, veb va platformalararo maydonlarda. Ikki yildan so'ng, ishonch bilan aytishimiz mumkin, React Native ko'p jihatdan inqilobiy. Bu mobil aloqa uchun paradigma o'zgarishi va biz uning ko'plab maqsadlariga erisha oldik. Biroq, uning foydalari og'riqli hislarsiz kelmadi.

Yaxshi ishlagan

Xoch-platforma

React Native-ning asosiy ustunligi shundaki, siz yozgan kod Android va iOS-da ishlaydi. React Native-dan foydalanadigan ko'pgina funktsiyalar 95-100% umumiy kodga erisha oldi va 0,2% fayllar platformaga tegishli edi (* .android.js / *. Ios.js).

Dizayn tillarining yagona tizimi (DLS)

Biz DLS deb nomlangan o'zaro faoliyat platformalar dizayni tilini ishlab chiqdik. Bizda Android, iOS, React Native va har bir komponentning veb-versiyalari mavjud. Birlashtirilgan dizayn tiliga ega bo'lish platformalar xususiyatlarini yozish uchun qulay edi, chunki bu platformalar bo'ylab dizaynlar, komponentlar nomlari va ekranlar izchil bo'lishini anglatadi. Ammo, biz imkon bo'lsa, platformaga mos keladigan qarorlar qabul qila oldik. Masalan, biz Android-dagi mahalliy asboblar panelidan va iOS-dagi UINavigationBar-dan foydalanamiz va Android-dagi oshkor qilish ko'rsatkichlarini yashirishni tanladik, chunki ular Android platformasi dizayni bo'yicha ko'rsatmalarga rioya qilmaydilar.

Biz asl nusxalarni o'rash o'rniga, tarkibiy qismlarni qayta yozishni tanladik, chunki har bir platforma uchun alohida-alohida platformaga mos API-larni yaratish yanada ishonchli va React Native-da o'zgarishlarni qanday qilib to'g'ri sinashni bilmagan Android va iOS muhandislari uchun texnik xizmat xarajatlarini kamaytirdik. Ammo, bu bir xil komponentning mahalliy va reaktiv mahalliy versiyalari sinxronlashadigan platformalar o'rtasida bo'linishni keltirib chiqardi.

Reaktsiya qiling

Reaktivning eng sevimli veb-doirasi ekanligiga sabab bor. Bu oddiy, ammo juda kuchli va katta kod bazalariga mos keladi. Bizga yoqadigan ba'zi narsalar:

  • Komponentlar: Reaktsiya komponentlari tashvishlarni aniq belgilangan rekvizitlar va shtatlar bilan ajratishni ta'minlaydi. Bu Reactning ko'lamini kengaytirishga katta hissa qo'shadi.
  • Soddalashtirilgan hayot tsikllari: Android va ozroq darajada, iOS hayotiy tsikllari juda murakkab. Reaktiv Reaktiv funktsional komponentlar ushbu muammoni tubdan hal qilishadi va React Native o'rganish Android yoki iOS-ni o'rganishdan ko'ra ancha soddalashtirildi.
  • Deklarativ: Reaktning deklarativ xususiyati bizning UI-ni asosiy holat bilan hamohang tutishga yordam berdi.

Iteratsiya tezligi

React Native-da rivojlanib borarkanmiz, biz Android va iOS-dagi o'zgarishlarimizni bir-ikki soniya ichida sinab ko'rish uchun issiq qayta yuklashdan ishonchli foydalana oldik. Tizimning samaradorligi bizning mahalliy ilovalarimiz uchun ustuvor vazifa bo'lsa ham, u hech qachon React Native yordamida erishilgan iteratsiya tezligiga yaqinlashmagan. Eng yaxshi holatda, mahalliy kompilyatsiya vaqti 15 soniyani tashkil qiladi, ammo to'liq qurish uchun 20 daqiqagacha bo'lishi mumkin.

Infratuzilmani investitsiyalash

Biz mahalliy infratuzilmani keng qamrovli integratsiyasini ishlab chiqdik. Tarmoq, i18n, tajriba, umumiy element almashinuvi, qurilma haqida ma'lumot, qayd hisobi ma'lumotlari va boshqalar kabi barcha asosiy qismlar yagona React Native API-ga o'ralgan. Ushbu ko'priklar ba'zi murakkabroq qismlar edi, chunki biz mavjud Android va iOS API-larini React uchun mos va kanonik narsaga aylantirmoqchi bo'ldik. Ushbu ko'priklarni tez iteratsiya va yangi infratuzilmani rivojlantirish bilan doimo yangilab turish doimiy rivojlanish o'yiniga aylangan bo'lsa ham, infratuzilma guruhining sarmoyasi mahsulot ishlashini ancha osonlashtirdi.

Infratuzilmani bunchalik katta sarmoyasiz, React Native subparpar dasturchi va foydalanuvchi tajribasini yaratgan bo'lar edi. Natijada, React Native dasturini salmoqli va doimiy ravishda sarmoya kiritmasdan turib, mavjud ilovaga osongina bog'lanishiga ishonmaymiz.

Ishlash

React Native atrofidagi eng katta tashvishlardan biri bu uning ishlashi edi. Biroq, amalda, bu kamdan-kam hollarda muammo edi. Aksariyat bizning Reaktiv Native ekranlarimiz xuddi o'zimiznikidek suyuqlik kabi. Ishlash ko'pincha bir o'lchovda o'ylanadi. Biz tez-tez mobil muhandislarning JS-ga qarashlarini va "Java-ga qaraganda sekinroq" deb o'ylashlarini ko'rdik. Biroq, asosiy mantiqiy ishbilarmonlik mantig'i va tartibini ko'chirish ko'p hollarda ishlash ko'rsatkichlarini yaxshilaydi.

Ishlash bilan bog'liq muammolarni ko'rganimizda, ular odatda haddan tashqari ishlov berish tufayli yuzaga kelgan va mustComponentUpdate, removeClippedSubviews va Redux-dan samarali foydalanish orqali kamaytirildi.

Biroq, boshlang'ich va birinchi namoyish qilish vaqti (quyida tasvirlangan) ishga tushirish ekranlari, chuqur chiziqlar uchun React Native ko'rsatkichini yomonlashtirdi va ekranlar o'rtasida harakatlanish paytida TTI vaqtini oshirdi. Bunga qo'shimcha ravishda, ramkalarni tashlab yuborgan ekranlarni disk raskadrovka qilish qiyin edi, chunki Yoga React Native komponentlari va ona nuqtai nazarlari o'rtasida tarjima qilingan.

Redux

Biz davlat boshqaruvi uchun Redux-dan foydalandik, natijada UI samarali va sinxron holatga tushib qolishining oldini oldi va ekranlarda ma'lumotlarni oson almashish imkoniyatini yaratdi. Biroq, Redux o'zining qozonxonasi bilan mashhur va nisbatan qiyin o'rganish chizig'iga ega. Biz ba'zi bir shablonlarni generatorlar bilan ta'minladik, ammo u hali ham React Native bilan ishlashda eng qiyin qismlardan biri edi. Ta'kidlash joizki, ushbu qiyinchiliklar Native Reative o'ziga xos bo'lmagan.

Native tomonidan qo'llab-quvvatlangan

React Native-dagi hamma narsani ona kodi bilan bog'lash mumkin bo'lganligi sababli, dastlab biz imkoni bo'lmagan ko'plab narsalarni qurishga muvaffaq bo'ldik:

  1. Umumiy elementlarga o'tish: Biz Android va iOS-da mahalliy sheriklik element kodi bilan quvvatlanadigan komponentini yaratdik. Bu hatto mahalliy va reaktiv ona ekranlar o'rtasida ishlaydi.
  2. Lotti: Biz mavjud kutubxonalarni Android va iOS-larga o'rab, Reot Native-da ishlashga muvaffaq bo'ldik.
  3. Native Networking stack: React Native ikkala platformada mavjud bo'lgan mahalliy tarmoq stakimiz va keshimizdan foydalanadi.
  4. Boshqa yadro infra: Xuddi tarmoq kabi, biz mavjud mahalliy infratuzilmani (masalan, i18n, eksperiment va boshqalar) o'rgandik, shunda u React Native-da muammosiz ishladi.

Statik tahlil

Biz Internetda eslintni ishlatishda kuchli tarixga egamiz, undan foydalana oldik. Biroq, biz Airbnb-da eng yaxshi kashshof bo'lgan birinchi platforma edik. Biz buni PR va velosipedda sayohat qilishni kamaytirishda samarali deb topdik. Endi Prettier veb-infratuzilmamiz jamoasi tomonidan faol ravishda o'rganilmoqda.

Shuningdek, ishlash vaqti bilan bog'liq muammolarni o'rganish uchun qaysi ekranlar ustuvorligini aniqlash uchun ishlash vaqtini va ishlashni o'lchash uchun tahlildan foydalandik.

React Native bizning veb-infratuzilimizga qaraganda kichikroq va yangi bo'lgani uchun, bu yangi g'oyalar uchun yaxshi sinov bo'ldi. Biz React Native uchun yaratgan ko'plab vositalar va g'oyalar hozirda veb tomonidan qabul qilinmoqda.

Animatsiyalar

React Native Animated kutubxonasi tufayli biz harakatlantiruvchi parallaks kabi zararsiz animatsiyalarga va hatto o'zaro ta'sirga asoslangan animatsiyalarga erishdik.

JS / Reaction Open Source

React Native haqiqatdan ham React va javascript-ni ishlaydiganligi sababli biz redux, qayta tanlov, hazil va hk kabi javascript loyihalarining juda katta to'plamidan foydalana oldik.

Flexbox

Rega Native tutqichlari tartibini yoga yordamida, moslashuvchan API API orqali tartiblash hisob-kitoblarini amalga oshiradigan kross-platformali C kutubxonasi. Erta boshda biz yoga cheklovlariga duch keldik, masalan aspekt nisbati yo'qligi, ammo ular keyingi yangilanishlarga qo'shildi. Bundan tashqari, bortda bortli fleksbok qurbaqa kabi qiziqarli darslar yanada yoqimli.

Internet bilan hamkorlik

React Native tadqiqotlarida kechikib, biz bir vaqtning o'zida veb, iOS va Android uchun qurishni boshladik. Veb shuningdek Redux-ni ishlatishini hisobga olib, biz veb-saytlarda va mahalliy platformalarda hech qanday o'zgartirishlarsiz tarqatilishi mumkin bo'lgan katta kodlarni topdik.

Nima yaxshi ishlamadi

Tug'ma tug'ma reaktsiya

React Native Android yoki iOS-ga qaraganda kamroq etuk. Bu yangi, juda talabchan va juda tez harakatlanuvchi. Aksariyat holatlarda React Native juda yaxshi ishlayotgan bo'lsa-da, uning kamolotga yetishi va mahalliy bo'lmagan narsalar uchun juda qiyin bo'lgan holatlar mavjud. Afsuski, bu misollarni oldindan aytish qiyin va ular har kuni bir necha soatdan ko'p kungacha ishlashlari mumkin.

Vakolatli ona qirqog'ini saqlash

Reaktiv ona tug'ilmaganligi sababli, ba'zida React Native manbasini tuzatishga to'g'ri kelgan. React Native-ga hissa qo'shishdan tashqari, biz o'zgarishlarni tezda birlashtira oladigan va versiyamizni puflab qo'yadigan vilka ushlab turishimiz kerak edi. Ikki yil davomida, React Native ustiga taxminan 50 ta topshiriqni qo'shishimiz kerak edi. Bu React Native dasturini takomillashtirish jarayonini juda og'riqli qiladi.

JavaScript vositasi

Javascript - bu tushunib bo'lmaydigan til. Xavfsizlikning yo'qligi, o'lchashni qiyinlashtirdi va React Native tilini o'rganishga qiziqishi mumkin bo'lgan terilgan tillarni o'rgangan mobil muhandislar uchun bahs mavzusiga aylandi. Biz oqimni qabul qilishni o'rganib chiqdik, lekin ishlab chiqaruvchilarning tajribalarini buzadigan sirli xato xabarlari paydo bo'ldi. Bundan tashqari, biz TypeScript-ni o'rganib chiqdik, ammo uni mavjud infratuzilmani (masalan, babel va metro to'plamlari) integratsiya qilish muammoli bo'lib chiqdi. Shu bilan birga, biz Internetda TypeScript-ni faol ravishda o'rganishda davom etamiz.

Qayta ishlab chiqarish

Javob berishning oldini olishning yana bir salbiy tomoni shundaki, refaktorizatsiya juda qiyin va xatolarga moyil edi. O'zgaruvchan rekvizitlar, xususan onClick kabi umumiy nom bilan ishlangan rekvizitlar yoki bir nechta tarkibiy qismlardan o'tgan rekvizitlar refaktorni aniq kiritish uchun dahshat edi. Eng yomoni, retseptorlar kompilyatsiya davrida emas, balki ishlab chiqarishni boshladilar va tegishli statistik tahlillarni kiritish qiyin edi.

JavaScriptCore nomuvofiqligi

React Native-ning nozik va murakkab jihatlaridan biri uning JavaScriptCore muhitida bajarilganligidir. Natijada quyidagilarga duch kelganmiz:

  • iOS o'z JavaScriptCore bilan ta'minlaydi. Bu shuni anglatadiki, iOS asosan izchil va biz uchun muammoli emas.
  • Android o'z Javascript-ni yuklamaydi, shuning uchun React Native to'plamlarini o'z to'plamlarini o'z ichiga oladi. Biroq, odatiy tarzda olingan narsa qadimiydir. Natijada, biz yangisini bog'lash uchun o'zimizdan chiqib ketishga majbur bo'ldik.
  • Nosozliklarni tuzatish paytida React Native Chrome Developer Tools nusxasiga biriktirilgan. Bu juda yaxshi, chunki u kuchli tuzatuvchidir. Ammo, nosozliklarni tuzatuvchi biriktirilgandan so'ng, barcha JavaScript-lar Chrome V8 dvigatelida ishlaydi. Bu vaqtning 99,9% yaxshi. Ammo, bir vaziyatda, toLocaleString iOS-da ishlayotganda biroz xatoga yo'l qo'ydik, lekin nosozliklarni tuzatish paytida faqat Android-da ishladik. Aniqlanishicha, Android AJ uni o'z ichiga olmaydi va V8-ni ishlatayotganingizda disk raskadrovka qilinmasa, u jim bo'lib qoldi. Bunga o'xshash texnik tafsilotlarni bilmasdan, mahsulot muhandislari uchun bir necha kunlik disk raskadrovka sabab bo'lishi mumkin.

Ochiq manbali ochiq manbali kutubxonalarni reaktsiya qilish

Platformani o'rganish qiyin va ko'p vaqt talab etadi. Aksariyat odamlar faqat bitta yoki ikkita platformani yaxshi bilishadi. Xaritalar, video va hk kabi ko'priklarga ega bo'lgan ona kutubxonalari muvaffaqiyat qozonish uchun barcha uchta platformalarni teng bilishni talab qiladi. React Native Open Source loyihalarining aksariyati faqat bitta yoki ikkitasi bilan tajribaga ega odamlar tomonidan yozilganligini aniqladik. Bu Android yoki iOS-da nomuvofiqliklar yoki kutilmagan xatolarga olib keldi.

Android-da, ko'plab React Native kutubxonalari, shuningdek, jamoat kutgan narsalarga zid bo'lgan ma'dan artefaktlarini nashr etishdan ko'ra, node_modules-ga nisbatan nisbiy yo'ldan foydalanishingizni talab qiladi.

Parallel infratuzilma va xususiyatli ish

Biz Android va iOS-da ko'p yillik mahalliy infratuzilmani to'pladik. Ammo, React Native-da biz bo'sh shiferdan boshladik va mavjud bo'lgan barcha infratuzilmalarning ko'priklarini yozishga yoki yaratishga majbur bo'ldik. Bu shuni anglatadiki, mahsulot muhandisi hali mavjud bo'lmagan ba'zi funktsiyalarga muhtoj bo'lgan paytlar bo'lgan. Shunda, ular yo o'zlari tanish bo'lmagan va o'z loyihalari doirasidan tashqarida bo'lgan platformada ishlashlari kerak edi yoki uni yaratish uchun blokirovka qilishdi.

Crash Monitoring

Biz Bugsnag-ni Android va iOS-larda nosozliklar haqida xabar berish uchun ishlatamiz. Umuman olganda, biz Bugsnag-ni ikkala platformada ham ishlashga muvaffaq bo'ldik, ammo bu bizning boshqa platformalarimizga qaraganda kamroq ishonchli va ko'proq ish talab qildi. React Native bu sohada nisbatan yangi va noyob bo'lganligi sababli, biz manba xaritalarini uyga yuklash kabi katta hajmdagi infratuzilmani qurishga majbur bo'ldik va Bugsnag bilan ishlashimiz kerak edi, shunchaki filtr halokati kabi narsalarni qila olamiz. Native reaktsiya.

React Native atrofidagi maxsus infratuzilma miqdori tufayli, biz vaqti-vaqti bilan nosozliklar haqida xabar berilmagan yoki manba xaritalari to'g'ri yuklanmagan jiddiy muammolarga duch kelamiz.

Va nihoyat, React Native-ning nosozliklarini tuzatish ko'pincha React Native va ona kodi yozilgan bo'lsa, yanada qiyinlashdi, chunki stack izlari React Native va mahalliy o'rtasidagi farq qilmaydi.

Ona ko'prigi

React Native mahalliy va reaktiv millat o'rtasida aloqa o'rnatish uchun ko'prik API-ga ega. Kutilganidek ishlayotgan bo'lsa ham, yozish juda qiyin. Birinchidan, barcha uch muhitni to'g'ri sozlashni talab qiladi. JavaScript-dan kelib chiqadigan turlar kutilmagan bo'lgan ko'plab muammolarga duch keldik. Masalan, butun sonlar ko'pincha torlar bilan o'ralgan bo'lib, bu masala ko'prik orqali o'tmaguncha tushunilmaydi. Bundan ham yomoni, ba'zida iOS ishlamay qolganda Android buziladi. Biz 2017 yil oxiriga qadar TypeScript ta'riflaridan avtomatik ravishda ko'prik kodini yaratishni o'rganishni boshladik, ammo juda kech edi.

Ishga tushirish vaqti

React Native birinchi marta namoyish qilishdan oldin, siz uning ish vaqtini boshlashingiz kerak. Afsuski, bu bizning o'lchamimizdagi ilova uchun, hatto yuqori darajadagi qurilmada ham bir necha soniya vaqtni oladi. React Native-ni ishga tushirish ekranlari uchun bu deyarli imkonsiz edi. Biz React Native uchun birinchi dastur vaqtini dasturni ishga tushirishda boshlash orqali minimallashtirdik.

Dastlabki yuborish vaqti

Asosiy ekranlardan farqli o'laroq, React Nativeni namoyish qilish uchun kamida bitta to'liq asosiy oqim kerak -> js -> yoga layout thread -> ekranni birinchi marta namoyish qilish uchun etarli ma'lumot mavjud bo'lgunga qadar. IOS-da o'rtacha 280 p90 va Android-da 440ms dan iborat dastlabki p90 ko'rsatilishini ko'rdik. Android-da, biz ekranni ko'rsatilgunga qadar kechiktirish uchun odatda elementlarni almashish uchun foydalaniladigan postponeEnterTransition API-dan foydalandik. IOS-da biz React Native-dan navbar konfiguratsiyasini etarlicha tez sozlashda muammolarga duch keldik. Natijada, konfiguratsiya yuklanganidan so'ng navbarning miltillashiga yo'l qo'ymaslik uchun barcha React Native ekran translyatsiyalariga 50 millimetrlik sun'iy kechikishni qo'shdik.

Ilova hajmi

React Native shuningdek, ilova hajmiga sezilarli ta'sir ko'rsatmaydi. Android-da React Native (Java + JS + mahalliy kutubxonalar, masalan, Yoga + Javascript Runtime) umumiy hajmi ABI uchun 8 mb bo'lgan. Bitta APK-da x86 va qo'llar (faqat 32 bit) bilan, u 12mb ga yaqinroq bo'lar edi.

64 bitli

Ushbu muammo tufayli biz hali ham Android-ga 64 bitli APK yuborolmaymiz.

Imo-ishoralar

Biz murakkab imo-ishoralarni o'z ichiga olgan ekranlar uchun React Native-dan foydalanishni xohlamadik, chunki Android va iOS uchun sensorli quyi tizim etarlicha farq qilganligi sababli, birlashtirilgan API-ni yaratish butun React Native hamjamiyati uchun qiyin bo'lgan. Biroq, ish o'sishda davom etmoqda va ona-imo-ishoralar bilan ishlaydiganlar faqat 1.0 ni urishdi.

Uzun ro'yxatlar

FactList kabi kutubxonalar bilan React Native bu sohada ba'zi yutuqlarga erishdi. Biroq, ular Android-dagi RecyclerView yoki iOS-dagi UICollectionView-ning etukligi va moslashuvchanligi haqida hech qanday ma'lumotga ega emaslar. Ko'pgina cheklovlarni iplar tufayli engib o'tish qiyin. Adapter ma'lumotlariga sinxron ravishda ulanib bo'lmayapti, shuning uchun tez aylanish paytida asinxron ko'rinishda ko'rinishini ko'rishni ko'rish mumkin. Matnni ham sinxron ravishda o'lchab bo'lmaydi, shuning uchun iOS oldindan hisoblangan hujayra balandligi bilan ma'lum optimallashtirishni amalga oshira olmaydi.

Reaktiv tubjoyni takomillashtirish

Garchi React Native-ning ko'pgina yangilanishlari arzimas bo'lsa-da, ulardan ba'zilari og'riqli bo'lib chiqdi. Xususan, React 16 alfa va beta-dan foydalanganligi sababli React Native 0.43 (2017 yil aprel) dan 0.49gacha (2017 yil oktyabr) foydalanish deyarli imkonsiz edi. Bu juda muammoli edi, chunki veb-foydalanish uchun mo'ljallangan React kutubxonalarining aksariyati React versiyalarini qo'llab-quvvatlamaydi. Ushbu yangilanish uchun tegishli bog'liqliklarni hal qilish jarayoni 2017 yil o'rtalarida React Native infratuzilmasining boshqa ishlariga katta zarar etkazdi.

Kirish imkoniyati

2017 yilda biz kirish imkoniyatlarini mukammal ta'mirladik, unda biz nogironlarning Airbnb-dan foydalanib, ularning ehtiyojlarini qondira oladigan ro'yxatni bron qilishlari uchun katta kuch sarfladik. Biroq, React Native accessibility API-da juda ko'p teshiklar mavjud edi. Qabul qilinadigan minimal to'siqni qondirish uchun biz reaktsiyalarni tugatish uchun o'zimizning vilkalarimizni saqlashimiz kerak edi, bu erda biz tuzatishlarni birlashtirishimiz mumkin edi. Bunday holatda, Android yoki iOS-dagi bir qatorli tuzatish uni React Native-ga qanday qo'shish kerakligini, gilosni terib olishni, so'ngra React Native yadrosiga masalani yuborishni va keyingi haftalar davomida buni kuzatishni davom ettirishga to'g'ri keladi.

Noqulay halokatlar

Biz tuzatish qiyin bo'lgan bir nechta g'alati avariyalarga duch keldik. Masalan, biz hozirda @ReactProp izohida ushbu avariyani boshdan kechirmoqdamiz va uni biron bir qurilmada, hattoki bir xil texnik va dasturiy ta'minotga ega bo'lganlarda ham, yovvoyi tabiatda halokatga uchragan qurilmalarda qayta ishlab chiqara olmadik.

SavedInstanceState Android-dagi barcha jarayonlar

Android tez-tez fon jarayonlarini tozalaydi, lekin ularni bir to'plamda sinxron ravishda saqlab qolish imkoniyatini beradi. Ammo, React Native-da, barcha holatlarga faqat js mavzusida kirish mumkin, shuning uchun buni sinxronlash mumkin emas. Agar bunday bo'lmasa ham, davlat do'koni sifatida redux bu yondashuvga mos kelmaydi, chunki u seriyalashtiriladigan va seriyalanmaydigan ma'lumotlarning aralashmasidan iborat va saqlanganInstanceState to'plamiga mos keladigan ma'lumotlardan ko'proq bo'lishi mumkin, bu esa avariyaga olib kelishi mumkin. ishlab chiqarish.

Bu React Native bilan bo'lgan tajribamizni va Airbnb-da mobil uchun keyingi imkoniyatlarni yoritadigan bloglardagi xabarlarning ikkinchi qismidir.

  • 1-qism: Airbnb-da tubjoy reaktsiyasi
  • 2-qism: Texnologiya
  • 3-qism: Kross-platformali mobil jamoani yaratish
  • 4-qism: tubjoy reaktsiya to'g'risida qaror qabul qilish
  • 5-qism: Mobil uchun keyingi narsalar