React Native — одного JS мало

  • Tutorial

Итак, пришла пора быстро погрузиться в тему. Для усиления эффекта, использую разные техники преобразования информации в знания. В частности, представляю конспект доклада Алексея Андросова (старшего разработчика интерфейсов, Yandex).


React Native — это фреймворк для разработки кроссплатформенных приложений для iOS и Android:


  • появился в начале 2015 года
  • построен на базе React
  • не использует WebView и HTML-технологии
  • нативные компоненты имеют биндинги в JS и обернуты в React
  • поддержка iOS лучше, чем Android, но динамика многообещающая

Первый ли он? Нет!


  • PhoneGap — реализация нативных компонентов на веб-технологиях, запускается в WebView
  • Xamarin — от разработчиков Mono для Linux, приложения написаны на C# (проект купил Microsoft)
  • NativeScript — похожие идеи, что и в React Native: XML + JS + CSS

Инструменты разработчика


  • Ваш любимый редактор JS
  • XCode и $100 в год на Developer account, чтобы собирать и публиковать приложения
  • Терпение + Android Studio + SDK + Эмулятор

React Native: взгляд сверху


  • Релиз примерно раз в 2 недели
  • Все прелести early adopters: несовместимые изменения, stackoverflow driven development
  • Все тот же обычный React

React Native: взгляд изнутри


  • нет HTML, но есть компоненты платформы в JSX
  • нет CSS, но есть CSS-like полифилы
  • нет DOM API. Вообще. Совсем.
  • ES6/ES7 и всё, что может babel, но нет JIT (на iOS)

Write once, run everywhere? Нет! Вместо ожидаемых предположений, что один и тот же код будем использовать многократно на разных платформах. Learn once, write everywhere. Одинаковая архитектура приложения (React для построения интерфейса, Redux для круговорота данных).

Немного философии


Все нативно, поэтому забудьте про полную кроссплатформенность. Платформы разные, поэтому и компоненты разные. У них разная логика и механика взаимодействия. Можно писать все на JS и выкинуть понятие native, но вы этого не хотите. Native — это ваше преимущество!


На примере приложения Vine в iOS. Что принято делать в iOS? Внизу TabBar, в нем принято переключать экраны: главная, профиль, поиск. Сверху NavigationBar, и в нем принято писать название и кнопки слева-справа (слева обычно back стоит, а справа — какое-нибудь действие). А в Android все не так. Есть тоже NavigationBar, но он другой, в нем не принято кнопки делать. Для этого есть отдельный компонент, называется ToolBar-ом. В Android-е принято делать SegmentedActivity — она сверху, очень похожа на iOS TabBar, но механика работы у него абсолютно другая. Если в TabBar-е мы не можем свайпом переключать экраны, то в Android-е это можно делать, и это принято делать, и именно так оно и работает.


Кроссплатформенность


  • интерактивные компоненты (навигация, меню, ...) будут разные
  • из-за этого раскладка приложения может быть разной
  • логические компоненты приложения будут одинаковые, и в это главная прелесть

Из чего состоит приложение?


  • нет привычных div, span, button, input и т.п.
  • нет привычного CSS
  • нет DOM

Компоненты


Приложение строится из компонент платформы — это нативные модули, завернутые в React-компоненты


  • есть кроссплатформенные: View, Text, Image, Picker, ...
  • есть специфичные для iOS: TabBarIOS, ActionSheetIOS, ...
  • есть специфичные для Android: BackAndroid, ToolbarAndroid, ...


[Вот так это выглядит, реальный код]


Интересно, что кнопок нет! Для вас любая кнопка — это просто стилизованная область, у которой есть обработчик нажатия. Никакой механики кнопки нет. И поэтому в React-е есть вот эти touchable-элементы, вы оборачиваете всё, что угодно и у вас всё что угодно становится кнопкой по сути (есть обработчик onPress). Scroll-ы — отдельный компонент. Это сегментированный вид. Он рендерит только то, что находится на экране, и с ним нужно работать чуть по другому. Потому ScrollView тут тоже отдельный. Отдельная механика, если используется клавиатура. Потому отдельное свойство есть — чего с ним делать. Отдельно свойство refreshControl. Если кто-то знает, как разрабатывать на iOS, то это очень похоже.



[Вот как выглядит текстовое поле]


Какие-то свойства совпадают с привычным HTML-input-ом, а другие — нет.


CSS не настоящий — это полифил


  • верстка абсолютными значениями, никаких относительных величин
  • для раскладки есть ограниченная реализация flexbox-свойств
  • полной поддержки CSSx никогда не будет, она не нужна
  • всего реализовано около 70-ти свойств, на самом деле их хватает; на всякий случай всегда есть SVG.


[Пример CSS #1]


Компонент PixelRatio преобразует значения из density points в настоящие пиксели для разных экранов (Retina и прочее).



[Пример CSS #2]


Вот это пример с flex-ом. Хватает минимального набора, чтобы верстать.


Болванка приложения


  • подключайте redux, без него будет совсем плохо
  • продумайте свои экраны и логику переходов
  • будут различия для iOS и Android
  • главным компонентом будет Navigator


[Пример кода приложения]



Имеет ряд проблем:


  • императивное API (методы) для управления
  • надо сразу продумать взаимодействие с Navigator
  • анимации и жесты сложно управляемы
  • NavigatorBar совсем отвязан от общей жизни
  • после разработки нескольких экранов вы начнете испытывать боль

Во многом, проблемы решаются с помощью redux.



[Почему это плохо?]


Чтобы запушить какой-нибудь роут, или сделать back (перемотать на другой экран) — надо сделать ссылку на Navigator, а потом эту ссылку получить. Причем изначально её не будет, т.к. Navigator-а еще нету.



[Интерфейс выглядит, как связанные компоненты]



[А на самом деле всё выглядит вот так]



  • не стоит пытаться связывать MyComponent и NavigationBar
  • лучше использовать global state и dispatch actions (flux/redux)


В декабре 2015 Eric Vicenti организовал проект navigation-rfc, с помощью сообщества, попытался решить проблемы Navigator. В феврале 2016 проект переехал в мастер React Native под название NavigationExperimental и теперь развивается силами Facebook. А старый Navigation больше не будет поддерживаться.



  • состояние управляется через reducer
  • вместо императивного API — action dispatcher
  • логика навигации отделяется от представления
  • разделение NavigationBar, анимаций и жестов управления на различные компоненты


[Пример кода навигации]


Анимации


  • реализуются через специальный компонент Animated
  • есть <Animated.View>, <Animated.Image>, <Animated.Text>
  • работают вне React, напрямую обновляя нативные компоненты


[Пример кода анимации]


Работает очень плавно, можно комбинировать последовательно/параллельно, и делать довольно безумные штуки.


Нативные модули


React Native реализует основные, но не все. Если модуля нет:


  • поискать компонент в UIExplorer (демо-приложение React Native)
  • найти правильное название модуля в терминах OS
  • поискать в исходных текстах, возможно он недокументирован (как фотку сделать, SVG)
  • js.coach/react-native — плагины для React Native
  • отдавайте предпочтение нативной реализации, а не JS

Как подключить нативные модули


Используйте rnpm — React Native package manager:


$ rnpm link react-native react-native-google-analytics-bridge

Кроссплатформенность компонент


Неправильный путь — разложить все по папкам:


  • common/components
  • android/components
  • ios/components

и подключать их в зависимости от платформы


Правильный путь — разложить все по папкам:


  • MyComponent/Component.ios.js, MyComponent/Component.android.js
  • ComponentIOS, ComponentAndroid

Для платформо-зависимых компонент (ComponentIOS, ComponentAndroid) удобно класть рядом пустышку, и не испытывать проблем, что какой-то компонент не найден на платформе.


Как написать нативный компонент


  • не надо писать все на JS
  • у компонента должна быть реализация в UIKit или Android API
  • если ее нет, то вы хотите странного, скорее всего

Финал доклада, видео с этого места.


PS


Коллега скинул ссылочку на Weex — две недели назад Alibaba передал проект Apache.


И опять внутри Vue. Что-то оно все время путается у меня под ногами.


Только проникся идеями React+Redux, бегаю с ними, как сумасшедший с бензопилой, в попытках везде применить. А тут что получается — разворачивай дебаркадер?!


Будет очень интересно почитать сравнение, может кто возьмется — тема на Хабре новая.

Share post

Similar posts

AdBlock has stolen the banner, but banners are not teeth — they will be back

More
Ads

Comments 84

    +1

    NavigationExperimental уже эволюционировал в https://reactnavigation.org/ "Learn once, navigate anywhere". Я не знаю всей истории, но похоже, что это будет рекомендованным решением (сейчас он на этапе беты).

      +3
      Собственно «вся история» старого навигатора заключается в том, что Navigator, ключевой компонент любого RN-приложения… не подчиняется React-логике! Когда в корневом элементе меняешь state, и Navigator получает таким образом новые проперти, он чхать на это хотел, а все переходы выполняются императивно, старыми-добрыми push() и pop(). С redux соответственно он тоже нифига не дружит.

      И об этом даже не написано в документации, хотя как раз об этом-то стоило упомянуть, ну не знаю, ЖИРНЫМ КРАСНЫМ МИГАЮЩИМ ЗАГОЛОВКОМ в самом верху описания компоненты.

      Разработчики RN на все зарепорченные на эту тему баги вяло отмахиваются, что решение это из перформанс соображений, а на просьбы хотя бы добавить информацию об этом в документацию отвечают почему-то «вам тут не стековерфлоу».

      Чем NavigatorExperimental по сути отличается от Navigator, в документации тоже не описано (спасибо автору статьи, теперь хоть буду знать).
      +1
      В 0.43 NavigationExperimental будет deprecated.
        0

        А как бы побыстрее собирать проект на этапе разработки под Android? На IntelXDK сборка проекта PhoneGap выполнялась шустро, если не путаю. Судя по видео в конце доклада, для Mac-а тоже Simulator готов к изменениям кода практически в реальном времени. А в Android Studio наблюдаю задержку 20 сек.

        +1
        • XCode и $100 в год на Developer account, чтобы собирать и публиковать приложения
        • Терпение + Android Studio + SDK + Эмулятор

        Можно немного срезать угол, по крайней мере на этапе прототипирования, если использовать Exponent:


        Exponent lets web developers build truly native apps that work across both iOS and Android by writing them once in just JavaScript.
        It's open source and free and uses React Native.
          +1
          как я понял, еxponet — это для написания собственных приложений в базовом приложении, чем-то похоже на AdobeAir. Ставишь на телефон exponet, а потом делаешь/загружаешь приложения для него.
          Верно?
            +1

            У них есть два режима и они не взаимоисключающие. Можно быстро и бесплатно получить своё приложение на телефоне запустив его через клиент, а можно собрать пакет и опубликовать в стор, тогда и появляется +$100 на iOS и +$50 на Android. Эта идея не нова, как минимум я такое видел для приложений "PhoneGap поколения", например, AppGyver.

            0

            Написал заметку про это чудо: Быстрый старт на React Native.

            +3

            Недавно закончил небольшой хобби проект
            Веб (react-native-web) + андроид (react-native).
            http://ru.quizexer.com/
            От работы с React Native остались по большей части положительные впечатление.
            Из всего кросплатформенных решений (веб/мобайл) что перепробовал, этот вариант считаю наиболее удачный.
            Да, есть баги и пока не хватает нативных модулей, но код получился практически идентичный,
            что для хобби проекта главный плюс.
            И вместо js можно использовать любой язык который в него компилируется, что тоже большой плюс.

              +1

              По опыту, каких компонентов не хватает? Автор доклада уверяет, что уже можно найти все, что угодно.

                +2

                Даже для такого простого приложия(хотя немного специфичного),
                пришлось написать два нативных модуля.
                1) для работы c SoundPool (Есть react-native-sound но это не совсем то и он немного глючный, крашил приложение на ряде устройств)
                2) для работы с Google Play Leaderboards.

              +1
              Выбор Redux для хранения глобального состояния чем обусловлен? Альтернативы рассматривались?
                0

                Redux — это архитектура приложения. Хотя камрады на Clojure со мной не согласны. У них свои велосипеды.

                  0

                  Насколько мне известно, Redux — библиотека (http://redux.js.org/ — Redux is a predictable state container for JavaScript apps. ), реализующая подмножество Flux архитектуры.

                    0

                    Из подмножества Flux, для меня очевидный выбор — Redux. Просто в силу его популярности, отсюда все вытекающие: документация, поддержка, расширения, вакансии, резюме. Так-то я уже наигрался с никому не нужными велосипедами.

                +4
                Интересно, что кнопок нет!

                Уже есть, старый способ кастомизации стилями тоже остался.
                подключайте redux, без него будет совсем плохо

                Почему не: «подключайте mobx, без него будет совсем плохо»?
                  0

                  Мопед не мой.

                  +1
                  Почему следует использовать именно React Native, вместо, к примеру, Cordova?
                    +2
                    UI получается нативный. Совсем другое ощущение от работы с приложением.
                      +1

                      Смысл такой: 2 потока, в основном — нейтивный гуй, во втором — логика на js.
                        +1

                        А что творилось с PhoneGap на iOS в мою бытность полтора года назад — это не передать литературными словами. Тогда и родилась мечта освоить React Native.

                          +2

                          Что же там творилось? И почему не NativeScript?

                            0

                            На видео выше — летает, если сравнивать с поделкой на Meteor-е. Второй проект PhoneGap на Phaser — уже лучше. Хотя там только HTML5-canvas, а все равно лаги. Crosswalk обещал помочь, но я этого уже не дождался.

                              +1

                              Cordova не виновата, то Ionic такой тормозной. Мы вот на $mol разрабатываем и ничего не тупит.

                                0

                                Не верю. Вся надежда на React Native и подобное.

                                  0

                                  Ну вот прямо сейчас пилю приложение на кордове:


                                    0

                                    Вполне!

                              0

                              NativeScript = Angular. Чур меня! :)

                                0

                                Ну, там и без него можно, но вроде как нативный интерфейс надо описывать на ихнем XML. Ещё они css парсят, а не в свойства пихают, как в RN.

                            +1

                            Ionic — редкостный тормоз. Нашли с чем сравнивать.

                              +1
                              Принцип тот же, отзывчивость интерфейса — примерно та же. Тут был смысл показать разницу в отзывчивости между вебвью и нейтивным гуем, пусть даже и с логикой на js.
                                +1

                                Я вам по секрету скажу — в WebView тоже можно использовать аппаратное ускорение анимаций.

                                  +1
                                  А никто про анимацию и не говорил — тут скорее сама сложность интерфейса в плане отрисовки и количества виджетов. Ну и не везде оно адекватно работает, те же тени на штатном андроид-браузере <= 4.0 адски тормозили и их приходилось отрубать.
                                    0

                                    Экран обычно не очень большой, так что число одновременно видимых виджетов весьма ограничено, что позволяет используя ленивый рендеринг получать хорошую отзывчивость.


                                    А в нативе не тормозили? Впрочем, емнип, начиная с 4 нативный браузер использует уже движок хрома. Ну и crosswalk подключается одной командой в консоли. Правда увеличивает бандл на 20 метров.

                          –2
                          Перед стартом нового проекта, мы в нашей компании изучили возможные варианты создания мобильных приложений с нативным UI. От React Native остались весьма негативные впечатления:

                          1. Инструменты для разработки очень глючные (по состоянию на месяц обратно), постоянно приходится что-то перезапускать.
                          2. React Native намертво привязан к React.
                          3. Продукт слишком сырой в целом: плохая документация, частые изменения API, куча багов в компонентах и т.д.
                          4. React Native ничего не знает про нативные стили компонент, создалось впечатление, что он на самом деле нативные компоненты вообще не использует, а тупо их эмулирует в нативном коде вместо WebView.
                          5. Приходится писать слишком много разного кода для двух платформ. С тем же успехом можно делать просто два нативных приложения и не страдать с глючным реактом.

                          Наш вывод: если есть желание использовать JS для разработки приложений, то стоит использовать NativeScript.
                            0
                            React Native намертво привязан к React.

                            Может это был основной вопрос? Я сам очень долго испытывал аллергию к JSX.

                              +1
                              Нет, не основной. Но такая привязка всегда минус. NativeScript и Cordova позволяют использовать что душе угодно.
                                0

                                React тянет за собой Redux (или навязывает, пока не разобрался до конца с глаголами). И это же счастье, когда мне кто-то говорит, как нужно обустроить порядок в проекте — снимает большой головняк, когда ресурсы ограничены. Мы все умрём, как известно. Просто некоторые относятся к вопросу беспечно.

                                  +1
                                  Абсолютно никакой связи между react и redux, как и между react и всеми производными от flux. Например, можете попробовать MobX. На хабре, кстати, тоже были статьи про него.
                                    0

                                    Я тоже думал, что вообще возьму Relay, и заживу наконец-то, как белый человек. Но Redux затягивает, и другого счастья мне уже не надо. :)

                                      +1
                                      Ну так то, что приглянулось одно из решений — это не значит, что react его требует или навязывает, это исключительно личное предпочтение :)
                                        +1
                                        Тоже сначала думал, что не надо никаких Redux'ов. Подёргался-подёргался, как муха в паутине, и затих. Нельзя сказать, что он мне понравился, просто [п]оказался единственным годным выходом.
                                          0

                                          Redux понравится не сразу, как и сам React :)

                                            0

                                            Мне Redux сначала нравился, когда знакомился только с его идеями, но потом всё меньше и меньше. Главное, что не нравится: Redux почти полностью игнорирует, что JS — ООП язык.

                                              0

                                              И тут я с ним согласен! Сублимация Clojure.

                              0
                              Инструменты для разработки очень глючные (по состоянию на месяц обратно), постоянно приходится что-то перезапускать.

                              Это видимо под Android, или под iOS тоже?

                                +1
                                Нет, я про консольные тулзы, что на компе работают. Всё очень сыро пока.
                                  0

                                  Какие, конкретно? Пожалуйста, подробности!

                                    +1
                                    Дев сервер постоянно тупит, например, и перестает подхватывать изменения.
                                      0
                                      facebook рекомендует ставить watchman из-за какого-то «бага» в отслеживании изменений в файлах, возможно это оно?
                                0
                                Наш вывод: если есть желание использовать JS для разработки приложений, то стоит использовать NativeScript.

                                Не понял, а вы ушли с JS?

                                  –1
                                  Мы для разных проектов используем разные технологии.
                                    0

                                    Всё в тумане! :)

                                +1
                                Поставил на Айпад демо-приложение от Weex. Очень положительные впечатления от скорости работы.
                                  +1

                                  Ожидаемо. Что будет со всеми теми же деталями по пунктам, которые озвучены в этом докладе?

                                  0

                                  Уточнил у автора доклада: какие компоненты использовал для SVG?


                                  Смотря для чего нужен svg.

                                  react-native-svg — это реализация svg поверх нативных компонент. Я ее как-то раз использовал, чтобы рисовать хитрые фигуры и круговые градиенты. react-native-svg-uri работает поверх нее и позволяет загружать svg из внешних источников. Ничего лучше для svg я пока не нашел.

                                  Если ты хочешь использовать svg-оконки, как это принято в вебе, то это плохоая идея. SVG работает не очень быстро. Лучше использовать обычные png через require, которые, например, можно генерировать из svg.
                                    +1

                                    Использовал react-native-svg для своей небольшой игры на ReactNative, остался доволен, т.к. покрывает отрисовку основных фигур и путей.

                                      0

                                      цитирую страждущего из лички:


                                      хочется svg для иконок интерфейса, например
                                      просто загрузил ассеты и показал
                                      2017 год ))
                                    0

                                    Разложите по полочкам, кто знает. Для разработки под Android — это неизбежные тормоза сборки? Пора переходить на Мак, или можно еще обождать?

                                      +2

                                      О какой сборки речь? Для RN нужно один раз собрать, потом подгружаются только изменения в js.

                                        0

                                        Я говорю о подобии HMR для веба, когда любое редактирование файла инициирует апдейт проекта.
                                        .

                                          +1

                                          И в чем вопрос?

                                            0

                                            Под Android сборка занимает до 20 секунд по опыту товарища. Судя по видео, под iOS сборка выполняется почти мгновенно.

                                              +1

                                              Сборкой занимается упаковщик RN. Он не привязан ни к ios ни к android.

                                                0

                                                Расшифруйте RN, пожалуйста.

                                                  0

                                                  Уже не надо, я осознал — React Native (RN).

                                      +1
                                      А в чем счастье, если, все равно, нужно писать отдельно ветки интерфейса для андроида, ios и web?
                                      Общие картинки и прочая статика?
                                      Что можно вынести в общую часть проекта?
                                        0

                                        Бизнес-логику, вестимо.

                                        +1
                                        Еще не совсем понял — при установке webstorm для компиляции проекта React Native требовал андроид студию и sdk версии 23 (т.е. от 6 андроида).
                                        Это что, правда, что React Native текущей версии не работает на более ранних андроидах?
                                          +1

                                          Новый сдк ведь и под старый андроид может собирать. Во всяком случае кордову под 4 я собирал.

                                          +1
                                          Полгода назад трогал RN, даже собирал несколько простеньких demo-приложений. В целом впечатления положительные, но пока не уверен что стал бы использовать React Native для проектов отличных от хобби\песочниц.
                                            +2

                                            Штука безусловно привлекательная, но огорчают некоторые моменты:


                                            • Глюки пока встречаются очень часто
                                            • Бардак в react-native/Libraries — без поиска найти нужный компонент очень затруднительно
                                            • Между некоторыми релизами очень трудно обновляться. Особенно досадно, когда зависишь от сторонней библиотеки, в которой поддержку новой версии внедрят через несколько месяцев, а то и никогда.
                                            • Зачастую разработчикам приходится пройти семь кругов ада чтобы влить PR
                                            • Проблемы выбора. До недавнего времени было 3 реализации навигатора, все 3 были признаны устаревшими, а рекомендуемое решение появилось только через 2-3 месяца, и то все-еще в бете.
                                            • Очень много неочевидных из документации моментов, подводных камней
                                            • Многие баги в JSX иногда очень трудно отлаживать, сообщения об ошибке не сильно помогают.

                                            Несмотря на это, продолжаю пользоваться и надеюсь на то что со временем детские болезни уйдут.


                                            Немного поправок,


                                            • rnpm уже включен в RN
                                            • в 0.42 появилась возможность задавать не только абсолютные величины, но и проценты
                                              +1

                                              Кстати, про неудобство отладки, обнаружил недавно трюк — дебаг при помощи console.log без вмешательство в код.

                                                +2

                                                Ещё в копилку :)


                                                (() => { debugger; })() || // anything

                                                Громоздкая, но полезная штука. Позволяет залезть внутрь труднодоступных мест. Скажем какие-нибудь binding-и knockout-а. Но по сути всё, что угодно, что выполняется через new Function или eval.

                                              0

                                              Как то я не удовлетворился нативным реактом, попробовал использовать сторонний компонент, все сломалось, попробовал кодить на виндах так он эмулятор андроида не видит. Короче как-то все выглядит сыровато и невдохновенно.

                                                0

                                                Меня вдохновляют результаты труда. А если преодолевая трудности, тем больше ценность достижения. :)

                                                +2
                                                https://itunes.apple.com/ru/app/millt-find-tattoo-artists/id1137884963?l=en&mt=8

                                                Полторы недели работы вместе с дизайном (чтобы понимали никогда до этого не писал под мобильные/javascript и вообще я дизайнер который прочитал статью, что дизайнер тоже должен кодить и пошел искать чтобы такого написать). Есть баги, но уверен, что нативно я бы писал это месяц.

                                                Что использовалось:
                                                1. Список с автоподгрузкой и пултурефреш
                                                2. Карты
                                                3. Кастомные экраны и анимация (просмотр мастера, на скрине в эпсторе видно)
                                                4. Реалтайм чат на сокетах
                                                5. Хранение внутри приложения данных

                                                Из интересного, не использовал redux, etc так как не знл что он существует, когда узнал было поздно, но в то же время многие опытные ребята говорят, что если ты справился без него, значит он тебе просто не нужен и не волнуйся на эту тему.
                                                  0

                                                  На счет "не нужен" сомнительно. Redux сильно облегчает жизнь.

                                                    +1

                                                    В то же время и осложняет. Особенно если императивный ООП подход ближе чем функциональный.

                                                    +1

                                                    Кроме Redux есть и другие библиотеки управления состоянием, хорошо интегрированные с React, реализующие другие подходы. А в целом, даже автор redux рекомендует сначала научить писать на голом реакте, а уж когда станет тесно, изучать редакс

                                                  Only users with full accounts can post comments. Log in, please.