React Native: Защо и как да изградите своя кодекс в движение

React Native ни позволява да изграждаме мобилни приложения, използвайки Javascript. За мен това е първата платформа, която всъщност изпълнява това обещание; това се прави чрез внимателна архитектура, най-доброто в класа инструментално оборудване и работния процес и прагматичен подход за разработване на крос-платформа. Не посочи, че целта му е да предостави възможност за писане на 100% Javascript код за всеки даден проект, нито обещаваше перфектна, единична, многоплатформена кодова база за вашите мобилни приложения. За мен това е цялата разлика.

И така, идеята за перфектно споделяне на кодове между платформи и приложение, което е изцяло изградено в Javascript, е по своята същност трудна, защото:

  1. Някои части, които трябва да изградите местно.
  2. Различните платформи са различни по опит.
  3. Различните устройства се представят по различен начин.
  4. Няма сребърен куршум.

Това означава, че в крайна сметка всички сме длъжни да напишем някакъв естествен код. Писането на нативен код е коренно изместване от нашия React Native опит: ние трябва да познаваме инструментите по-интимно; Xcode, Android Studio и Gradle и Android SDK, Obj-C или Swift и Java или всеки удобен за Android JVM език като Kotlin. Трябва също така да се запознаем с рамковия ментален модел на всяка платформа, като например „Intents and Views“ на Android и контролерите, изгледите и делегатите на Cocoa.

Защо да отидете Native?

Но преди това, дори когато сме в React Native, можем да изброим истински причини, които ни принуждават да се изхвърлим от Javascript и да отидем на местно ниво.

  • Производителност. Това може би е първият елемент, който пресича съзнанието на всички, когато казват „естествен код“, а това е и първият елемент, който трябва да потрудите усилено, за да го изключите. Първо трябва да докажете чрез числа, че имате проблем с представянето. И тогава бих останал подозрителен, ако бяхте ти. И все пак, родният код коства производителността на Javascript с добра степен за определени натоварвания.
  • Достъп до ОС на ниско ниво. Това вече е навсякъде около нас. Ние използваме React Native пакети, които се занимават с нативните части на всяка ОС, тъй като ядрото React Native все още не е стигнало до него или е извън обхвата.
  • Инфраструктура и здравина. Има задачи, които са напразно направени в Javascript двигателя, като обработка на изображения, преместване на големи количества байтове през моста React Native, обработка на файлове и др.
  • Лоша асинхронна логика. Може би предпочитаме да използваме нативните операционни системи за справяне с работните процеси в асинхронизацията или да предпочетем „локалните“ езикови конструкции за това. Различни ментални модели за едновременност като CSP и актьорския модел идват на ум.
  • Библиотеки и екосистема. Възможно е някои библиотеки да не са налични в npm или да нямат качеството, което очакваме, или функции или поддръжка на общността. Нативният вариант може да е вече златен стандарт.
  • Затъмнение и устойчивост на обратната техника. React Native Javascript код се доставя с вашия двоичен код и всеки може да го вземе от вашия пакет. Докато някои платформи като Xamarin криптират и вграждат в естествен код, той все още е там (PDF), за да може отпадащият да се отвори. В повечето случаи това не е проблем, но има много случаи, когато вашият IP всъщност е вашият код.
  • Споделяне на код с бекенд. Докато едно от основните предимства на използването на Node.js е споделянето на Javascript код на задния и предния интерфейс, може да се окаже, че вашият бекенд не е изграден на Node.js, нито на Javascript, а вие все още искате да споделяте артефакти като модел на данни , валидиране и бизнес правила.
  • И накрая, любимото ми: двоична комуникация. Въпреки че бихте могли да комуникирате през двоичен протокол, като Protobuf от вашия React Native процес, може да е болезнено и предизвикателно да разопаковате двоични данни или да постигнете добра ефективност и това да бъде поддържано или поддържано от съществуваща платформа и библиотеки.

С развитието на React Native, някои от елементите в този списък ще изчезнат, а някои от тях, като объркване и други, винаги ще останат.

Използване на Go for Cross-Platform Mobile Development

Разрешавайки гостуващи виртуални машини, които като Javascript поддържат език на дадена платформа или комерсиални двигатели като Apportable, ни остават C и C ++ (използван C ++ за падаща кутия за споделяне на не-потребителски код) като целеви езици за споделяне на родния код.

Но те не са безопасни (както в безопасността на паметта) и в сравнение с Javascript са твърдо ядро. Използването на Java, Obj-C или C / C ++ може да създаде значително количество на триене. Има и Rust, но не съм сигурен колко добре играе с ARM и какъв вид мобилни абстракции има (няма?).

До преди няколко години това можеше да свърши експеримента ни. Тогава Go (езикът) добави поддръжка за експорт на двоични файлове като C-библиотеки, което отвори свят на възможности. Например, преди години използвах Go, за да коригирам затрудненията в производителността в Ruby, а по-късно написах статия и референтна Gem изпълнение, за да покажа как бихте могли да го направите и вие.

Друг от тях беше пускането на мобилни устройства. Ще ви покажа, че Go е толкова добър език, който да използвате за облачна инфраструктура, както и за мобилна разработка и - до голяма степен - мобилна разработка за React Native.

Клонът ни от Призма: Праймер

Ще направим приложение, което изобразява изображения като това:

Ако се чудите на алгоритъма за обработка на изображения зад това изображение, той се нарича примитивен от Майкъл Фоглман и можете също да купите приложение за Mac, което той построи тук.

Ще вземем този алгоритъм и ще изградим около него мобилно приложение, където първоначално алгоритъмът е написан на Go.

И ето как ще изглежда на живо (видеото е на бърза скорост):

Тъй като основният алгоритъм е родният и е вграден в Go, ще го използваме такъв, какъвто е. Но за да бъдем ясни, ако трябваше да изградим този алгоритъм или друг алгоритъм или част от инфраструктурата, която трябва да е родна и вече не сме имали съществуваща кодова база, имахме трудно решение да вземем:

  • Изградете го два пъти в Java и Obj-C.
  • Веднъж в C / C ++.
  • Веднъж в Go.

Всъщност, за този конкретен случай и алгоритъм за използване, ние маркираме още повече елементи от списъка „защо отивам роден“ по-горе:

  1. Производителност. Go ще прояви по-добра производителност от Javascript (ще видим колко по-късно). Тук имаме нужда от него, тъй като примитивният е взискателен алгоритъм, базиран на процесора. Всъщност той е толкова взискателен, че прави обработката на тези изображения на силен iPhone бавна. Go е по-близо до метала тук и прави добър случай да го използвате вместо Javascript.
  2. Използване на библиотека, която не съществува в npm. И този път, тъй като това е нов алгоритъм, реализиран в Go, и няма порт от този никъде другаде, бях щастлив, че Go on mobile (а по-късно го направих да работи на React Native) работи толкова добре.
  3. Еквилибристика. В този случай целевата Go библиотека, която използваме, е с отворен код. Ако не беше така и се грижехте за своя IP адрес, никой не би могъл да обърне този алгоритъм, без да инвестира необосновано време.
  4. Роден достъп до API. Този алгоритъм може да запише моментни снимки на напредъка на диска при всяка итерация. Ако това би бил Javascript, трябва да кодираме всяка снимка и да я изпращаме като голям base64 низ през моста React Native.

И разбира се, можем да използваме един и същ естествен код както за Android, така и за iOS.

Go Mobile Toolchain

Ако вече сте запознати с Go като език, това ще бъде приятен свеж бриз. Ако не, за да се запознаете с Go, разгледайте турнето Go.

След като направите това, нека да инсталирате и упражнявате веригата за инструменти на gomobile (предполагам, че сте инсталирали Go и междувременно сте успели да направите просто „здравей свят“):

$ npm install -g ios-implementiranje
$ go get golang.org/x/mobile/cmd/gomobile
$ gomobile init # може да отнеме няколко минути
$ gomobile build -target = ios golang.org/x/mobile/example/basic
$ ios-implemen -b basic.app

Ако всичко работи добре, трябва да видите мобилно приложение във вашия симулатор. Това, което тази мобилна инструментална мрежа направи, е да създаде собствена iOS библиотека, да генерира скелетно приложение, да ги свърже и да пакетира приложение. Всичко стана тихо (или смирено?), Това е част от философията Go: успехът трябва да бъде мълчалив; с други думи - нито една новина не е добра новина.

Съветвам ви да прочетете кратката статия на Wiki. За да получите подходящ контекст за тези инструменти.

Свързване на React Native и Go Mobile

Започваме, като правим свежо приложение на React Native и тук грабваме примера на реагиращата камера. Това е удобен начин да стигнете до точката на тази статия, но може да искате да изградите своя от нулата.

Искаме сега да изградим нашата родна библиотека Go и да започнем, като я свържем с приложението ни за iOS. Това е мястото, където може да стане сложно, защото трябва да помислим за нашия работен процес преди всичко останало.

В Go, най-доброто нещо, което трябва да направите, е да разработите кода си Go във вашия GOPATH, който е убедено място, където живеят вашият Go код и библиотеките на трети страни (има твърда логика в това, но това е извън обхвата на тази статия) , И така първото ни решение е да поставим и нашата родна библиотека там - а не редом с нашето приложение.

Веднъж приятен бонус е, че новият ни пакет Go не знае факта, че ще го използваме на мобилно устройство. Всъщност можете удобно да работите върху него като самостоятелно приложение Go и след това да решите да го свържете с мобилното си приложение, когато сте готови.

За мен тя живее тук (вашите ще бъдат различни):

<Начало> /workspaces/golang/src/github.com/jondot/primer-bind

Оформлението е просто:

➜ дърво, свързано с грунд.
,
└── грунд
    └── prime.go

1 директория, 1 файл

Нека разгледаме нашия Go код:

Бърз пропуск показва, че експортираме OnIterationDone, който е обратен интерфейс като интерфейс, който ще използваме от всяка родна страна и Process, който е входната точка на нашия алгоритъм. Няма нищо особено за типове, влизащи и излизащи; go се грижи за генериране на код за прехвърлянето им на съответните мобилни платформи.

За Process взех CLI кода от примитива и го хакнах, така че да е функция, която мога да експортирам. Ние също изнасяме Bench и JsonDummy за нашата витрина.

Ще видите, че във всяка стъпка в тази статия аз предприемам най-малката възможна стъпка за стратегическо създаване на код, който можем да обсъдим без прекалено голям контекст.

След като това е налице, трябва да превключим контекста и CD към нашето приложение. Сега искаме да се възползваме от веригата инструменти за gomobile, така че ще стартираме това:

gomobile bind -x -v -target = ios github.com/jondot/primer-bind/primer

Той ще генерира родна библиотека за вас и ще плюе много подробности, докато правите това, защото използваме -x -v; но можете да ги пуснете, ако желаете. Можете да видите красотата на третирането на всеки Go код като пакет: ние предоставяме път, който е едновременно репо и локален път във вашия GOPATH, ако не разполагате с локално копие, Go ще го извлече и изгради, като го използвате, или оставете това такова, каквото е, и ще вземем пакета ми и ще го компилирам, така че да не се налага.

След това трябва да изградим мост в родния си код, за да залепим всичко заедно.

Ето, ние правим RCTEventEmitter, защото искаме да получим известие там, където родният алгоритъм Go завърши работата си. Ние също обгръщаме нашата OnIterationDone структура с по-хубав интерфейс Obj-C. За мястото, където седят хедъри, тя корелира с нашия Go пакет (избрахме грунд).

Наблюдение: ето как бихте изградили нативния модул, независимо от Go. Искаме да имаме функция за асинхронизация от естествената страна, която получава променливи като брой повторения, размер, режим и брой на работниците и обратно извикване, предавайте ги на нашата Процесна функция, наречена GoPrimerProcess, която се генерира автоматично за нас, отново тя корелира с име на пакета и име на функция, представено с „Go“.

Това е основно. Частта Javascript сега започва и отново ще направим това като всяко друго лепило за родния модул:

андроид

За Android това ще бъде още по-лесно, защото ние имаме поддръжка на Android Studio чрез плъгин Gradle. Не забравяйте, че все още имаме същото изпълнение на Go пакета, недокоснато, на едно и също място. Трябва да уточним това местоположение в Gradle и да предаваме родния мост на Android в Java.

Това ще бъдат същите стъпки, които трябва да направите във всяко приложение за Android и Go. За повече информация можете да разгледате референтния проект и тук.

Както всеки основен компонент на Android в React Native, ние имаме нашия модул, който съдържа интересните битове и пакета, който инструктира React Native да инжектира нашия модул.

Сега, нашия мостов код. Част от модула:

И пакетната част:

Кодът на нашия модул Java показва, че пакетът Go магически се появява в go.primer и под псевдо-обект, наречен Primer (колко удобно!). Обърнете внимание, че gomobile генерира Go страна за вас и идиотски го поставя като истински Java модул.

С това завършва грандиозна обиколка: Отидете, iOS (мост), Javascript (лепило) и Android (мост).

Гранд тур

Това е обиколка на четири езика, извършване на водопроводни работи: В Go, ние свързахме истинския модул Go, за да направим функция, която можем да експортираме чисто. В iOS създадохме вграден модул и го свързахме към родната библиотека, която не е различна от която и да е друга C библиотека по този въпрос. В Javascript ние свързахме естествената част към кода от страна на приложението, който не е различен от всичко, което бихме направили за обикновен нативен модул. Затваряйки, на Android, ние създадохме приятна конфигурация на сглобяване и обикновен мост на родния модул.

По-голямата част от тази инвестиция във водопроводни работи ще бъде същата, ако създадем всеки местен модул. Разликата тук е, че сега имаме една единствена, базирана на Go, кодова база, с която да работим - и в дългосрочен план това ще спести много време, защото няма нужда да поддържаме едни и същи паралелни кодови бази на Android и IOS.

Въпросът за изпълнението

Как работи кодът ни в Javascript в сравнение с Go? Ще изпълним глупав показател, който вероятно е подвеждащ за вземане на решение в реалния живот, така че не го приемайте като факт и можете да опитате на живо в PrimerApp. TL; DR е, че Go е 2 пъти по-бърз от Javascript за този и този показател.

заключение

Go with React Native е мач, направен в небето за следните сценарии:

  • Вие сте страстен за Go или вече имате съществуващ код в Go или искате да споделите резервен Go код с мобилното си приложение. Разбира се, специално за това имате и GopherJS, който работи изключително добре.
  • Имате нужда от ефективност.
  • Искате инфраструктурната устойчивост и типовите стойности за безопасност на Go.
  • Искате собственият код да остане в безопасност.
  • Не искате да изразявате идеи както в Obj-C / Swift, така и в Java.

Със сигурност има повече мотивация да съвпаднеш Go with React Native, но вярвам, че този малък списък беше това, което ще срещаш всеки ден. С това се надявам да ви е харесало този синтез на технологии и че ще дойдете да изградите нещо интересно с идеите, които ви показах тук.

Можете да намерите референтното приложение тук и модула Go тук.

Също така, аз съм страстно да залича дублирането на нативен код. Ако имате нужда от помощ за този ход, пуснете ми ред на dotan@paracode.com.

Hacker Noon е как хакерите започват следобедите си. Ние сме част от семейството на @AMI Сега приемаме заявления и се радваме да обсъдим възможностите за реклама и спонсорство.
Ако ви е харесала тази история, препоръчваме ви да прочетете нашите най-нови технологични истории и тенденциозни технологични истории. До следващия път не приемайте реалностите на света за даденост!