company_banner

Переработка архитектуры React Native в 2020 году

Автор оригинала: Rémi Gallego
  • Перевод
Фреймворк React Native (RN) появился в 2015 году. Он предназначен для разработки кросс-платформенных мобильных приложений с использованием библиотеки React. Эти приложения поддерживают нативные возможности платформ, для которых их создают. У исходной архитектуры React Native были определённые недостатки. Но, несмотря на это, RN получил хорошую поддержку сообщества, его популярность постепенно росла, не в последнюю очередь — благодаря громкой репутации React.



О проекте по перепроектированию архитектуры React Native заговорили в 2018 году. Этой работой занимается команда Facebook. Цель перепроектирования заключается в том, чтобы сделать фреймворк более стабильным, и в том, чтобы решить наиболее распространённые проблемы, накопившиеся в RN за годы разработки. Материал, перевод которого мы сегодня публикуем, посвящён рассмотрению того, как переработка архитектуры RN способна улучшить производительность приложений и скорость работы программистов.

Старая архитектура


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

  • Корректное формирование интерфейса.
  • Обеспечение доступа к нативным возможностям различных платформ.

Обычно, в экосистемах Android/iOS, механизм, используемый для решения этих задач, выглядит примерно так, как показано на следующем рисунке.


Существующая архитектура React Native (источник)

В каждом React Native-приложении параллельно выполняются три следующих потока:

  • Поток JS. Это — поток, в котором осуществляется чтение и компиляция JavaScript-кода. Здесь же выполняется основная часть логики приложения. Бандлер Metro комбинирует весь JS-код в единственный файл, отвечает за обработку JSX- и TS-конструкций. Затем полученный код отправляют движку JavaScriptCore, средствами которого этот код может быть запущен.
  • Поток Native. Здесь производится выполнение нативного кода. Этот поток взаимодействует с JavaScript-потоком тогда, когда нужно обновить интерфейс или обратиться к нативным функциям. Этот поток можно разделить на две части. Первая, Native UI, отвечает за использование нативных средств формирования интерфейса. Вторая, Native Modules, предоставляет доступ к особым возможностям платформы, на которой работает приложение. Она готова к работе после запуска приложения. То есть, например, если React Native использует Bluetooth-модуль, он всегда будет активным, даже в том случае, если он, на самом деле, не используется.
  • Поток Shadow. В нём выполняется пересчёт макета приложения. Здесь используется движок Yoga, являющийся собственной разработкой Facebook. В этом потоке выполняются вычисления, связанные с формированием интерфейса приложения. Результаты этих вычислений отправляют потоку, ответственному за вывод интерфейса.

Для организации взаимодействия между потоками JS и Native используется модуль Bridge (мост). Этот модуль написан на C++, в его основе лежит асинхронная очередь. Когда мост получает данные от одной из сторон, он сериализует эти данные, преобразуя в строковой вид, и передаёт их через очередь. Когда данные прибывают в пункт назначения, они десериализуются.

Это означает, что все потоки полагаются на асинхронные JSON-сообщения, передаваемые через мост. Каждая из сторон отправляет эти сообщения, ожидая (но не имея гарантии) того, что когда-то в будущем на эти сообщения будет получен ответ. При такой схеме обмена данными существует риск перегрузки канала связи.

Вот пример, который обычно приводят, чтобы проиллюстрировать то, как подобная схема обмена данными способна вызвать проблемы с производительностью приложения. Предположим, что пользователь приложения выполняет прокрутку огромного списка. Когда в нативной среде происходит событие onScroll, информация асинхронно передаётся в JavaScript-окружение. Но нативные механизмы не ждут до тех пор, пока JavaScript-часть приложения сделает своё дело и им об этом отчитается. Из-за этого возникает задержка, выражающаяся в появлении в списке, перед выводом его содержимого, пустого пространства.

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

Как видно, отправка JSON-данных с использованием асинхронных механизмов, а также сериализация и десериализация этих данных, вызывают проблемы с производительностью. Этот механизм несовершенен. Но как ещё можно наладить взаимодействие между нативными механизмами и JavaScript? Ответить на этот вопрос можно с помощью технологии JSI.

Новая архитектура


В ходе перепроектирования архитектуры React Native выполняется постепенный отказ от функций моста, на смену которым приходит новый механизм, называемый JavaScript Interface (JSI).

Применение JSI открывает возможности для некоторых замечательных улучшений.

Первое такое улучшение заключается в том, что JS-бандл больше не полагается на JSC. Другими словами, движок JSC теперь легко можно заменить на что-то другое, вполне возможно, отличающееся более высокой производительность. Например — на движок V8.

Второе улучшение — это то, что лежит в основе новой архитектуры React Native. Оно заключается в том, что, благодаря использованию JSI, в JavaScript можно хранить ссылки на C++-объекты (Host Objects) и вызывать методы этих объектов. В результате оказывается, что JavaScript-часть приложения и нативные механизмы будут знать друг о друге гораздо больше, чем раньше.

Иными словами, JSI позволяет обеспечить полное взаимодействие между всеми потоками. Благодаря использованию концепции совместного владения (shared ownership), JavaScript-код может запускать нативные методы непосредственно из JS-потока. При этом нет необходимости в том, чтобы использовать JSON для передачи данных. Это позволяет избавиться от проблем, характерных для использования моста, связанных с возможным переполнением очереди и с асинхронной передачей данных.


Новая архитектура React Native (источник)

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

Этот новый механизм может открыть дорогу к разработке новых проектов, способных на то, что было недоступно старым RN-приложениям. Дело в том, что теперь в нашем распоряжении оказалась мощь C++. А это значит, что на базе React Native теперь можно будет создавать гораздо больше разновидностей приложений, чем раньше.

Итоги


За годы развития в инфраструктуре React Native накопилось много такого, что сегодня можно признать устаревшим и неиспользуемым. Стремление разработчиков RN к тому, чтобы убрать из него ненужное и улучшить возможности по его поддержке, ведёт к удалению некоторых его возможностей. Например, речь идёт о том, что модули его ядра, вроде Webview и AsyncStorage, постепенно выводятся из состава фреймворка и оформляются в виде репозиториев, развиваемых силами сообщества React Native.

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

Ожидается, что реструктуризация React Native завершится в 4 квартале 2020 года. Меня восхищают те перспективы, касающиеся производительности приложений и удобства разработки, которые открываются благодаря переработке архитектуры RN.

Если вы пользуетесь React Native — расскажите о том, с какими недостатками этого фреймворка вам довелось столкнуться.



RUVDS.com
RUVDS – хостинг VDS/VPS серверов

Комментарии 15

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

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

    Наверное убирание бриджа устранит часть проблем, но я что-то не верю про 2020 — они уже явно отстают от графика.

    Для примера — последнее с чем столкнулся вчера — не работает DeepLink из Android при холодном старте. 5 лет фреймворку, а баги такого уровня ;( И таких проблем просто прорва.
      +3
      Пишу на RN уже 3.5 года. На Flutter около года. И я хочу сказать, что то, что другое, это очень условно готовый продукт, который иногда работает, а иногда нет, и никто и никогда не даст гарантии, что то, что работает у тебя, будет работать у других. Все что сложнее CRUD'а — это боль, мобильная разработка это место отчаяния.
        0
        Меня пока очень впечатлил потенциальный контроль над всем View уровнем во Flutter.
        Но хочется посмотреть как там сложные примеры реализованы — что-то типа BottomSheet cо ScrollView внутри
      +1
      А доступ к нативному апи платформы (без моста) появится?
        –2

        Конечно, нет.

          0
          Конечно появиться, но тут вопрос наверное не верно сформулирован

          Для доступа к нативному API все равно придется писать библиотеку. Данные будут передаваться через JSI, не через бридж. Это будет чем то похоже на то, как сейчас в Chrome реализованы функции типа String.fromCharCode

          Могу только сказать что если нужно получать какие-то данные от платформы — то это тривиально, но все равно раздражает. Как-то разработчикам из NativeScript удалось же без этого обойтись

          ViewManagers не делал пока

          0
          а зачем они в принципе пробуют спасти React Native? Почему бы просто не забить на него и начать юзать Flutter?
            +1
            Есть определенные плюсы в том, когда у компании все разработчики умеют React.

            А уж у Facebook то сам бог велел извлекать из этого бонусы :)

            В Shopify также говорят «мы используем React Native, потому что дофига уже вложили в код на React и это экономит нам бабки».

            Есть еще определенные нюансы, про то что на Flutter сделать качественное приложение ни чуть не проще чем на RN, просто сложности другие — приложение медузы тому пример, но это уже холивар.

            Я думаю так — если эта переделка пойдет удачно, то RN и дальше будет развиваться.
            Если нет — то постепенно стухнет.
              0
              спасибо за ответ
                0

                У медузы проблемы с тем, что писали дилетанты, а не потому что у Flutter "другие проблемы". Одна только работа с изолятами вызывает смех…

                  0
                  А есть исходник? Или что?
                    0
                    Есть подкаст, где они рассказывают о сложностях с которыми столкнулись и как они это обходили. Одно только «Мораль простая: если что-то надо вынести из Main Isolate используйте Compute.» вызывает смех.
              0

              RN отлично годится для того чтобы быстро разрабатывать приложения которые работают с данными. Но как только начинаются взаимодействия с нативными функциями приходится танцевать с бубнами. RN хорош когда надо реализовать +100300 приложение площадку для заказчика с супер крутой идеей и совсем не годится для разработки мессенджера

                –1

                RN — это один большой кусок дерь... костыль. простите...
                Я понимаю, что он стал популярен, потому что React, но не понимаю, почему оно до сих пор живо. Кроме боли и страдания лично я ничего от не ощутил и не приобрел.
                P.S. всё выше озвученное — сугубо личное мнение и никому его не называю и не считаю его единственно верным

                  0
                  Как и Electron…

                Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

                Самое читаемое