В соавторстве с Сааром Берковичем и Майклом Островским.

Выпуск первого iPhone в 2007 году вызвал серьезный прорыв в индустрии мобильных телефонов, вызвав «золотую лихорадку», напоминающую Дикий Запад и чьи последствия все еще находят отклик сегодня, 10 лет спустя, во многих отраслях.

Если вы хотите создать всемирно признанное мобильное приложение в настоящее время, вы хотите, чтобы оно было доступно как для Android, так и для iOS. Вы можете (и, возможно, должны) запустить его на одной из двух платформ, но когда и если вы получите поддержку, пользователи начнут обращаться к вам с просьбой сделать приложение доступным для их платформы. Такой подход служит тревожным звонком, который вы упускаете для 30–70% владельцев смартфонов как потенциальных пользователей (в зависимости от вашей демографической группы).

Около года назад мы начали оценивать React Native как средство для создания кроссплатформенного мобильного приложения. Разработка Snipe для мобильных устройств началась во втором квартале 2018 года и до сих пор базировалась исключительно на React Native. Это включает в себя: реализацию видения продукта, создание MVP, его выпуск в App Store и Play Store и его наращивание с помощью регулярных обновлений программного обеспечения.

Фон

Первоначальная идея приложения Snipe заключалась в том, чтобы помочь геймерам найти хороших товарищей по команде для игры - проблема, которая широко распространена во всем мире соревновательных игр и киберспорта, - путем революционного изменения способов их решения. Геймерам больше не нужно будет полагаться на свою удачу при поиске товарищей по команде, используя внутриигровой подбор игроков (где основное внимание уделяется созданию честных матчей между двумя противоположными группами), рассылке спама на серверах Discord или просмотру форумов. на основе веб-сайтов. Альтернативой, которую мы должны были предложить, является подбор игроков для товарищей по команде на базе ИИ (с использованием моделей машинного обучения и технологии рекомендательных систем) на сервере и мобильного приложения для клиента, чтобы пользователи могли найти людей, с которыми можно поиграть позже, в течение дня.

Мы собрали техническую команду с разным опытом, но так уж получилось, что наш совместный опыт разработки мобильных приложений на тот момент добавился к нескольким приложениям для Android в стиле «Hello World». Это, а также желание выпустить как на iOS, так и на Android, сделали обещание React Native очень привлекательным для нас.

React Native - это поддерживаемый Facebook набор инструментов с открытым исходным кодом (под лицензией MIT), который позволяет создавать кроссплатформенные мобильные приложения (на iOS и Android) на JavaScript (с использованием JavaScriptCore, движка JavaScript WebKit) на основе React с веб-стилем и синтаксисом разметки, аналогичным CSS и HTML. Он существует с 2015 года и используется такими компаниями, как Airbnb, Wix и Discord, что делает его, пожалуй, самым зрелым и широко используемым из решений для разработки кроссплатформенных приложений (другие похожие решения, которые приходят на ум: Native Script , Apache Cordova , Microsoft Xamarin и недавно выпущенный Google Flutter ).

Как мы вскоре обнаружили, создание кроссплатформенных приложений React Native с нуля не обходится без препятствий, с которыми разработчики, занимающиеся разработкой типичных мобильных приложений, редко сталкиваются.

Остальная часть этого поста будет посвящена нашему опыту разработки с React Native - что нам нравится, что нет и когда мы рекомендуем его использовать. Следует отметить, что мы используем React Native v55 (который появился довольно недавно, но не новейший).

Добро

React Native сертифицирован для быстрой и грязной работы. В среде стартапа быстрое выполнение итераций является ключевым моментом. Помимо того факта, что вы пишете код для обеих платформ одновременно, использование нетипизированного языка, такого как JavaScript, по существу позволяет проводить итерации быстрее (при этом возможно ухудшение стабильности в виде ошибок - имейте это в виду).

Возможность совместного использования языка программирования для обеих платформ означала, что мы смогли взять существующее приложение для iOS и выпустить его в Android Play Store менее чем за неделю (!). Это не то, что мы могли бы сделать, если бы приложение было написано на чистом Swift или Objective-C.

Тот факт, что React Native сильно вдохновлен и основан на веб-технологиях, означает, что разработчики с опытом работы в Интернете будут чувствовать себя как дома. Чего нельзя сказать о новичках в разработке приложений с использованием собственных SDK, поскольку они реализуют проприетарные форматы для разработки пользовательского интерфейса. Это особенно актуально для организаций (и частных лиц), которые глубоко связаны с веб-технологиями, такими как Wix (которые широко используют React Native).

Еще одно преимущество использования JavaScript заключается в том, что он позволяет повторно использовать код в Интернете и даже на рабочем столе (с использованием Electron и т.п.). Хотя вы не сможете поделиться кодом целиком (в основном потому, что React Native JSX не идентичен HTML и CSS), вы, по крайней мере, сможете поделиться своим слоем модели (в терминах MVC).

Сообщество большое и растет, это означает, что постоянно появляются новые библиотеки, а старые становятся все более отточенными. Кроме того, большинство проблем, с которыми вы столкнетесь на этом пути, можно решить с помощью простого поиска в Google. Сами по себе решения не всегда могут быть простыми, но информация, безусловно, есть.

Плохо

React Native не полностью кроссплатформенный. Между React Native, работающим на iOS и Android, существует множество несоответствий. Приведу несколько примеров:

  • Укладка ведет себя иначе. Многие изменения макета, которые изначально тестировались на одной платформе, в конечном итоге нарушили работу другой, даже при аналогичных разрешениях экрана.
  • Многие функции и готовые к использованию компоненты, предоставляемые React Native, доступны только для одной из платформ. Например, недавно мы хотели добавить кнопку очистки для ввода текста. Документы указали нам, что существует встроенное решение для iOS, которое включает изменение свойств нашего элемента TextInput. К сожалению, встроенного решения для Android не было.
  • Ошибки часто несовместимы, пример которых будет описан в следующем пункте.

обработка ошибок и отладка могут быть действительно болезненными. Не говоря уже о том, что ошибки JavaScript могут быть загадочными сами по себе, проблемы с исходной картой, сгенерированной во время упаковки / транспиляции, приводят к тому, что ошибки JS указывают на неправильные номера строк, в результате чего вам приходится угадывать код, где возникла ошибка.
Ошибки, относящиеся к внутреннему устройству React Native (помимо JS-кода), могут быть еще более ужасными, поскольку они часто совершенно непонятны для любого, кто не знаком с внутренней работой самого React Native.

Вышеупомянутая ошибка является примером ошибки в Android, когда часть JSX в проекте не может быть проанализирована Yoga (механизм компоновки, используемый React Native). У нас была эта ошибка, приводившая к сбою Android после итераций тестирования, разработанных и протестированных на симуляторе iOS, где он работал нормально.

Установка библиотек - это кошмар - желание выполнить любое собственное взаимодействие, не реализованное в React Native, требует, чтобы вы загружали библиотеки (обычно через npm или GitHub) и «связывали» их с соответствующими собственными проектами, изменяя части. собственного кода и сборки файлов конфигурации вручную (или запуск автоматизации, которая может или не может сломать весь ваш проект). Процесс компоновки очень подвержен ошибкам, и чем больше у вас библиотек, тем сложнее становится их добавить, поскольку библиотеки часто конфликтуют друг с другом из-за зависимостей и предыдущих изменений, сделанных для других библиотек. Этот процесс также будет принципиально отличаться для вашего приложения для Android и iOS, а это значит, что вам придется пройти его дважды.

Многие из этих библиотек реализуют функции, которые нам кажутся тривиальными, но отсутствуют в самом React Native. Вот некоторые из них: push-уведомления (!), Воспроизведение видео, встроенная навигация и поддержка карт.

Наконец, отсутствует поддержка React Native на Android. React Native на Android строго хуже, чем аналог для iOS, он поставляется со старым JavaScriptCore, в нем есть ошибки, которых нет в iOS, он использует устаревшие методы для сборки и работает заметно медленнее. Причина этого, по всей видимости, двоякая: iOS предпочитают Android в Facebook (хотя это не официально), а также Android, имеющий значительно больше возможных конфигураций оборудования, которые нужно оптимизировать и обслуживать.

Важно сделать оговорку, что не все эти проблемы являются ошибками в React Native, некоторые из них связаны с зависимостями React Native, некоторые с соответствующей ОС, и многие из них могут быть исправлены (например, проблема с исходной картой). Несмотря на это, вышеупомянутые проблемы привели к огромному снижению производительности и потере времени для нас, что привело к большому разочарованию и задержкам в доставке.

Уродливый

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

Дизайн пользовательского интерфейса - дополнительный источник возмущения. Приложения на Android и iOS следуют различным шаблонам и принципам проектирования, известным как Материальный дизайн и Рекомендации по человеческому интерфейсу соответственно. Хотя они заимствуют друг у друга, у них разные основы и рекомендации. Например, нижние панели навигации очень заметны в приложениях iOS, но их не рекомендуется использовать на Android. Google недавно изменил свою позицию и включил их в Material Design, но по-прежнему дает рекомендации по различным схемам окраски. Несоблюдение указанных рекомендаций приводит к плохому UX, поскольку пользователи используются для того, чтобы их приложения имели определенный внешний вид.

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

React Native действительно упрощает кодирование и рендеринг различных версий компонентов в зависимости от платформы, позволяя использовать if (Platform.OS === ’ios’) {} else {} блоки или указывая разные файлы, полностью основанные на платформе, но если вы собираетесь столкнуться с проблемой написания почти всего дважды, оправдывает ли это смирение с остальными упомянутыми болевыми точками? На наш взгляд, это не так.

Финальная перестрелка

Разработка в React Native во многом похожа на просмотр вестерна - боевые сцены быстрые и захватывающие, но создание к ним может быть медленным и утомительным. По состоянию на начало 2019 года React Native все еще чувствует себя незрелым и в конечном итоге не выполняет обещание о «кроссплатформенной мобильной разработке», которое, учитывая упомянутые различные рекомендации по дизайну пользовательского интерфейса, может никогда не быть полностью .resolve()’d.

Мы рекомендуем использовать React Native для создания простых приложений и отбрасываемых MVP или прототипов, или если вы собираетесь выпустить только для iOS, где он намного более стабилен (именно так Discord катится). Однако, если вы планируете работать над сложным долгим проектом, который должен быть выпущен на обеих платформах, мы считаем, что React Native не подходит для вас.

Airbnb недавно прекратил работать с React Native (после того, как был активным пользователем в течение 2 лет) и написал об этом подробный, состоящий из 5 частей, пост в блоге.

Что касается нас, мы скоро будем стремиться к полной нативности на обеих платформах (tm). На данный момент мы чувствуем, что развитие нашего ядра в React Native сдерживает нас.