Исполнит ли React Native мечту программиста: единый код для web, android и ios?
Писать код — сложно. Писать код для нескольких платформ — еще сложнее. Программисты это знают, и последние двадцать лет идеи «универсального всемогутора» будоражат умы и воплощаются в разные технологии. Начиная от Java и заканчивая phonegap разработчики очень хотели, чтобы один раз написал и везде работало. Но не складывалось.
А потом facebook сделал ReactJS. Чтобы чат себе починить. И сложилось. Идея сборки интерфейса из javascript «кубиков» оказалась настолько хороша, что facebook портировал фреймворк на мобильные платформы, сделав сначала React Native для iOS, а через полгода и для Android. Сможет ли технология, пришедшая из веба, сделать то, что не получилось у таких монстров, как Java и .NET?
Давняя мечта: write once, run anywhere
Кроссплатформенная разработка стала популярна совсем недавно. Еще пятнадцать лет назад слово «программа» было синонимом «программа под windows». Подавляющее большинство компьютеров работали на windows. В параллельном мире энтерпрайз решений жили HP-UX (более известное как «чпукс»), серверный линукс и джава. В другом параллельном мире — макось с фотошопом и иллюстратором. Миры не пересекались, программы создавались под конкретные платформы и кроссплатформенные решения были скорее курьезом, чем необходимостью.
А потом случилось несколько вещей. «Выстрелили» мобильные платформы, выросла популярность маков, кардинально упростилась покупка и аренда софта. Программы начали использовать все, а не только «компьютерщики». И неожиданно оказалось, что давний слоган Java «write once, run anywhere» стал очень актуален. Огромному количеству компаний, начиная от банков и заканчивая старбаксом, понадобились приложения. Желательно — сразу для всех актуальных платформ. Крайне желательно подешевле. И совсем хорошо, если прямо сейчас.
Мечте мешают design guides и скорость выполнения
Разработчики было стряхнули пыль с проверенных инструментов, но оказалось, что не все так просто. Подавляющее большинство технологий кроссплатформенной разработки, доступные на мобильных платформах, сами рисуют пользовательский интерфейс. Отчего он, во-первых, выглядит чужеродно. А, во-вторых, тормозит. Добавим к этому «протекающие абстракции»: любое сложное приложение рано или поздно выходит за рамки кроссплатформенного фреймворка и приходилось расширять его «родным» кодом, что часто приводит к проблемам взаимодействия между расширением и самим фреймворком.
Фреймворки и библиотеки, призванные решать эту проблему, начали плодиться как грибы после денежного дождя: Appcelerator, Phonegap, Xamarin, FireMonkey, NativeScript. Но особую популярность никто не завоевал, а в интернете стали появляться статьи вида «как мы начали делать банк-клиент на название фреймворка и через год выкинули его, перейдя на натив».
React приносит адаптивный дизайн из веба в мобайл
И тут, в середине 2015 года, Facebook представляет React Native. На первый взгляд, ничего нового. JavaScript, из которого можно создавать «родные» элементы пользовательского интерфейса как на iOS, так и на Android. У Appcelerator такое уже было много лет.
Дьявол скрывался в деталях. Сборка интерфейса «из кубиков» и заимствованный из веба «адаптивный» подход к дизайну позволили сделать интересную штуку. Используя React, интерфейс верстается семантически, как в вебе. Вместо того, чтобы оперировать элементами интерфейса ios или android, дизайнер создает интерфейс из логических компонент: «экран», «заголовок», «список», «кнопка». А уже сверстанный интерфейс доводится напильником до конкретных платформ: несколько строчек кода превращают компонент «прогресс» в набор HTML тегов для веба, ProgressBarAndroid для android и ProgressViewIOS для ios.
Такой подход очень удобен: вначале интерфейс быстро верстается из универсальных блоков, а затем дорабатывается под каждую платформу только там, где это действительно надо. Это удивительно напоминает адаптивную верстку, когда вначале верстается универсальный «резиновый» интерфейс, а затем с помощью @media дорабатывается под экран телефона, экран планшета и большой экран.
Прототип приложения теперь можно сделать за пару дней
В качестве примера посмотрим на тестовое приложение для нашего React Native SDK. С помощью SDK можно совершать и принимать обычные или видео звонки, включая бесплатные peer to peer. А приложение показывает, как им пользоваться: окно логина, окно ввода номера или имени, россыпь кнопочек вида «позвонить», «включить видео», «отключить микрофон» и тому подобных. Если посмотреть на исходник, то мы увидим один код, работающий на обоих платформах. Отличается код только там, где мы сами этого захотели. К примеру, используется нативная версия переключателя, поэтому его имплементация разделена на два файла: ColorSwitch.ios.js и ColorSwitch.android.js
Демо приложение было сделано за два дня. Сразу под ios и android. А если мы захотим сделать версию для веба, то это займет от силы еще день (да, web sdk у нас есть и да, он может звонить из браузера благодаря магии webRTC). Все что нужно будет сделать — это заменить элементы пользовательского интерфейса на div«ы и поменять несколько вызовов sdk, которые отличаются между веб и мобайл версией.
Peer-to-peer
{settings_p2p = value}}/>
Video
this.videoSwitch(e)}/>
Все ли так гладко на практике?
С каждым месяцем все больше компаний используют ReactJS и React Native. Тем не менее, технология еще очень молодая (android версии всего несколько месяцев от роду), и все «детские болезни» идут в комплекте.
В первую очередь хочется отметить малое количество элементов интерфейса, которые доступны «из коробки». Полтора десятка универсальных и по десятку специфичных для ios и android. Можно легко «обернуть» любой нативный элемент, но это потребует знаний java, objective-c или swift. Альтернативный вариант — использовать один из сотен созданных энтузиастами элементов, доступных на github. Но open source специфичен — иногда проблем от небрежно написанных элементов больше, чем если делать их самому.
Молодость технологии также ограничивает выбор доступных библиотек и биндингов. На момент анонса React Native у нас уже давно были нативные sdk для ios и android. Пользуясь этим, мы сразу приступили к портированию и первыми запаковали webRTC в React Native. Но все равно это заняло довольно много времени: пока изучишь документацию, пока напишешь код, пока все протестируешь, пока continuous integration настроишь — для серьезных библиотек это может быть вопрос не одного месяца.
Скорость развития фреймворка тоже не всегда играет на руку разработчикам. При обновлении на последнюю версию у нас неожиданно перестало воспроизводиться видео, при этом в логе не то что ошибок — даже предупреждений не было. Долгое копание в коде показало, что авторы «всего лишь» перенесли в другое место ReactProp для Android. Такие изменения, конечно, случаются не часто –, но все еще бывают, особенно для версии под Android.
import com.facebook.react.uimanager.*;
import com.facebook.react.uimanager.annotations.ReactProp;
public class VoxImplantViewManager extends SimpleViewManager
Выводы
Технология очень перспективная, но молодая. Из прямых конкурентов я могу назвать «windows universal apps» от Microsoft с похожей концепцией семантической верстки интерфейса, недавно усиленной технологией continuum. И «Xamarin.Forms», предлагающий похожее решение с «универсальными» и «платформо-специфичными» элементами интерфейса. Но у React есть перед ними ряд преимуществ: web как одна из платформ, сверхпопулярный JavaScript, не менее популярный тулчейн node.js, бесплатность, поддержка facebook и «hot reloading» из коробки.
Можно сказать, что сейчас React Native можно использовать для быстрого прототипирования мобильных версий ваших веб приложений. Причем если веб приложение уже написано на ReactJS, то скорость переноса возрастает в разы. Создание сложных приложений с публикацией в сторах уже возможно, это хорошо видно в галерее. Но будьте готовы к тому, что финальное «доведение до ума» затянется и потребует лезть в java и objective-c.
P.S. А чат они себе так и не починили. Но там, походу, и правда место проклято.