[перевод] React Native — проект Bridge to the Fabric (новая архитектура RN)

React Native

Автор: Чен Фельдман

Дата выпуска: 2019.07.30

Оригинальная ссылка:medium.com/ коммерческий пилот / реагировать- ...

Некоторые из переводов являются бесплатными переводами.

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

Для разработки с помощью RN требуются веб-знания и опыт работы с React, поскольку он в основном основан на платформе React. Это немного сложнее, чем напрямую использовать такую ​​библиотеку, как Cordova, но намного проще, чем писать код для двух нативных клиентов, Swift и Kotlin. RN может получить производительность, аналогичную нативной, путем написания чистого кода js.

Часть 1: В чем заключается черная магия RN's Bridge?

Прежде чем мы начнем, давайте сначала представим, каково позиционирование React Native по сравнению с другими решениями.

img
На приведенном выше рисунке выбраны некоторые распространенные методы разработки приложений.

Слева направо его можно разделить на 3 лагеря:

  1. Родной Родной. Это означает, что вы хотите разрабатывать приложения на родных языках, таких как Swift для iOS или Kotlin для Android. Вы определенно получите максимальную производительность и в полной мере воспользуетесь аппаратным обеспечением устройства и собственными API. Однако это требует изучения двух разных языков программирования, поддержки двух наборов кода и, возможно, удвоения количества ошибок и даже двух разных групп разработчиков.

  2. Гибридный. Если вы веб-разработчик или у вас есть веб-команда, уже знакомая с JS, HTML, CSS и некоторыми внешними библиотеками, вы можете выбрать этот вариант и использовать Cordova/Ionic, чтобы превратить свою веб-страницу в мобильное приложение за несколько шагов. Таким образом, нам нужно изучить только один технологический стек, однако будут ограничения в производительности, аппаратном обеспечении и использовании API.

  3. Класс нативный (на самом деле гибридный). React Native попадает в эту категорию.Теоретически разработчикам нужно знать только знания веб-разработки. Но кривая обучения будет немного выше, чем у гибрида. Разработчикам необходимо научиться использовать библиотеки React Native. В некоторых сценариях также может потребоваться открыть проект с помощью XCode или Android Studio. Однако написанный код можно применять как для платформ iOS, так и для Android, а ограничения на разработку будут меньше, чем у Hybrid. Производительность будет больше похожа на нативную разработку, а некоторые нативные API-интерфейсы можно будет использовать проще.

Теперь, когда мы понимаем позиционирование RN, давайте сравним рендеринг RN и Hybrid:

img

Как видно из рисунка выше, приложение, использующее Cordova, размещается в webView. Это больше похоже на браузер внутри приложения. В веб-терминах это больше похоже на iFrame в веб-приложении.

Слева показано, как устроен React Native.Каждый компонент в RN, такой как текст, кнопка, изображение и т. д., имеет соответствующий нативный компонент. Таким образом, в отличие от того, что думают многие новые разработчики RN, RN не компилируется в собственный код, а создает сопоставление между компонентами JS и собственными компонентами.

Когда мы написали компонент RN в функции рендеринга:

img

Задняя часть предварительно написанных нативных компонентов будет выглядеть так:

img

Если мы используем iOS в качестве примера, это нативные коды компонентов в RN:

img

В целом, команда RN создала и сопоставила для нас все нативные компоненты. Все, что нам нужно сделать, это написать код JavaScript на основе компонентов и библиотек RN. Другие части невидимы для среднего разработчика, как черная магия.

Итак, похоже, мы можем просто написать код js. Давайте объясним шаг за шагом, как выглядит эта архитектура. Правильнее всего начать с Bridge:

RN можно разделить на JS и Native, у каждого из которых есть свои потоки.

Связь потока осуществляется через связь Bridge, которая передает информацию JSON, содержащую идентификатор модуля, идентификатор метода и некоторые необходимые данные. Две стороны не воспринимают друг друга напрямую и не разделяют одну и ту же память.

img

Это немного похоже на общение между разными серверами.Если у вас есть серверные службы, написанные на разных языках, как вы будете общаться между ними?

Многие люди думают, что очереди — хорошее решение. Вы отправляете сообщения очереди JSON/XML, которые соответствуют соответствующему протоколу, и каждая служба знает, как читать и анализировать их в соответствующие данные и поведение. Эта очередь очень похожа на мост в RN.

img

Вот пример, показывающий, как работает связь, информация отправляется в Bridge. От создания новых представлений и стилей и их отображения на экране до настройки дочерних компонентов на мобильных устройствах и выполнения нескольких действий:

img

Если вы хотите увидеть сообщение Bridge в консоли, просто поместите следующий фрагмент кода в index..js.

img

Теперь, когда мы знаем, как общаются RN, мы начинаем раскрывать причастную к этому «черную магию».

  • Связь между кодом js и target-c. RN использует встроенный JCore на iOS и должен скомпилировать Js-движок на Android.
  • JS-движки знают, как более эффективно конвертировать JS в машинный язык.

Вот почему для загрузки Android-приложения требуется больше времени, потому что в проект необходимо загрузить JCore. Однако после версии 0.60.2 RN может использовать Hermes, который является более идеальным JS-движком для RN.

Часть 2: Как работает мост?

В этой части мы проанализируем процесс от щелчка значка приложения до открытия приложения и некоторых связанных деталей.

img

Чтобы понять, как RN создает представления за кулисами, нам сначала нужно объяснить некоторые основные понятия:

  1. UIManager: на нативной стороне это основной поток, работающий в iOS/Android. Только у него есть разрешение на изменение пользовательского интерфейса клиента.
  2. Поток JS: запустите упакованный файл main.bundle.js, который содержит всю бизнес-логику, поведение и компоненты RN.
  3. Теневой узел/дерево: Собственное дерево на уровне компонентов может помочь отслеживать изменения пользовательского интерфейса в приложении, что немного похоже на отношения между ReactJS в виртуальном Доме и Доме.
  4. Йога: используется для расчета макета. Это движок C, написанный Facebook для преобразования макета на основе Flexbox в систему нативной компоновки.

Теперь, когда вы понимаете некоторые из приведенных выше основных понятий, давайте посмотрим, что происходит на каждом этапе, когда вы открываете приложение:

  1. Пользователь щелкает значок приложения

  2. Поток UIManager: загрузить все собственные библиотеки и собственные компоненты, такие как текст, кнопка, изображение и т. д.

  3. Сообщите потоку Js, что нативная часть готова, и сторона Js начнет загружать main.bundle.js, который содержит всю логику и компоненты js и реакции.

  4. Сторона Js отправляет сообщение JSON на сторону Native через мост, сообщая Native, как создать пользовательский интерфейс. Стоит отметить, что все коммуникации через Bridge асинхронны и отправляются пакетами. Это делается для того, чтобы избежать блокировки пользовательского интерфейса, например:

img

  1. Теневой поток сначала получает сообщение, а затем создает дерево пользовательского интерфейса.

  2. Затем он использует механизм компоновки Yoga, чтобы получить все макеты на основе flex и преобразовать их в собственные макеты, такие как ширина, высота, интервал и т. д. .

  3. После этого UIManager выполняет некоторые действия и отображает пользовательский интерфейс на экране следующим образом:

    img

Это основные шаги для запуска приложения.

РН на основе этой архитектуры имеет следующие преимущества:

  • Пользовательский интерфейс не заблокирован: пользователь чувствует себя более плавным
  • Не нужно писать код на нативной стороне: если использовать библиотеку RN, много кода можно написать только на JavaScript
  • Производительность ближе к Native
  • Весь процесс завершен. Разработчикам не нужно контролировать и полностью понимать это

Однако есть преимущества и недостатки. Теперь давайте представим новую архитектуру, которая устраняет существующие недостатки: Fabric.

Часть 3: Преимущества и недостатки мостовой и тканевой архитектуры

Теперь, когда мы обсудили текущую архитектуру RN, пришло время поговорить о ее недостатках. Взгляните на руководителя команды Facebook React в ее образе.блогупоминается в.

Недостатки существующей архитектуры:

  • Есть две разные области: JS и Native, между собой и они не могут реально воспринимать друг друга, и не могут делить одну и ту же память.
  • Связь между ними представляет собой асинхронную связь на основе моста. Но это также означает, что нет никакой гарантии, что данные дойдут до другой стороны 100% и вовремя.
  • Передача больших данных очень медленная, потому что память не может быть разделена, и все данные, передаваемые между js и нативом, являются новой копией.
  • Не удалось синхронно обновить пользовательский интерфейс. Допустим, есть FlatList, который загружает много данных, когда я смахиваю. В некоторых граничных сценариях, когда есть взаимодействие с пользовательским интерфейсом, но данные не возвращены, экран может мерцать.
  • Хранилище кода RN слишком велико. Это приводит к тому, что библиотека становится более тяжелой, а сообщества с открытым исходным кодом медленнее вносят свой код или выпускают исправления.

Но не поймите меня неправильно, Facebook сам использует React Native для разработки различных приложений, ежедневно обслуживающих миллионы активных пользователей. Есть и другие известные компании, использующие RN на основе текущей архитектуры в производственной среде, такие как Wix, Bloomberg, Tesla, Zynga и др.

Команда разработчиков RN работает над устранением упомянутых выше недостатков.

Вот предыдущая архитектура RN:

当前结构的主要部分

Вот схема новой архитектуры:

img

Давайте объясним эти новые концепции: JSI, Fabric, Turbo Modules и CodeGen.

  1. JSI (заменит Bridge) — чтобы JS и Native знали друг о друге. Больше не будет необходимости передавать сериализованный JSON через Bridge. Позволяет экспортировать нативные объекты как объекты Js и наоборот. Обе стороны также экспортируют API, которые можно вызывать синхронно. Собственно, на этом и основана вся остальная архитектура (Fabric, Turbo Modules и т.д., о которых ниже)

  2. Fabric — новое имя для UIManager, который будет отвечать за собственный рендеринг. В отличие от текущего моста, он может экспортировать свои собственные функции через JSI, и эти ссылки на функции могут использоваться непосредственно на уровне JS, который, в свою очередь, также может напрямую вызывать уровень JS. Это приводит к лучшей и более эффективной производительности и передаче данных.

  3. Турбо модули. Помните компонент Native выше? Text, Image, View, их новое название Turbo Modules. Роль компонента та же, но реализация и поведение будут другими. Сначала они загружались лениво (загружались только тогда, когда они нужны приложению), а теперь все они загружаются при запуске. Кроме того, они экспортируются через JSI, поэтому JS может получить ссылку на эти компоненты и использовать их в React Natvie JS. В частности, это повысит производительность при запуске.

  4. CodeGen — сделать сторону JS единственным источником правды при общении между двумя сторонами. Это позволяет разработчикам создавать статические классы JS, чтобы нативная сторона (модули Fabric и Turbo) могла их распознавать и избегать проверки данных каждый раз => повысит производительность и уменьшит вероятность ошибок при передаче данных.

  5. Lean Core — это изменение архитектуры библиотеки React Native. Цель состоит в том, чтобы облегчить нагрузку на библиотеку и помочь сообществу быстрее решать больше запросов на вытягивание. Facebook открывает части библиотеки, и вы можете увидеть, что они делают, подписавшись на Github. Например это:

    img

Кстати, вот пример, который вы можете попробовать в Chrome, который также является источником вдохновения для того, как JSI работает и экспортирует объекты:

Откройте интерфейс разработчика в Chrome, затем введите console.log и нажмите Enter. Вы увидите нативный код. Это показывает, что console.log на самом деле является нативной функцией.

在Chrome里打开开发者界面,然后输入console.log,回车。你将看到native code

Далее давайте сравним процесс запуска приложения с использованием новой архитектуры.

  1. Пользователь щелкает значок приложения

  2. Fabric загружает нативную сторону (без нативных компонентов)

  3. Затем уведомите поток JS о том, что нативная сторона готова, и сторона JS загрузит все main.bundle.js, которые содержат все js и логику реакции + компоненты.

  4. JS вызывает Fabric через ссылку на собственную функцию (экспортируемую JSI API), а Shadow Node создает то же дерево пользовательского интерфейса, что и раньше.

  5. Yogo выполняет расчет макета для преобразования макетов на основе Flexbox в макеты терминала.

  6. Fabric выполняет действие и отображает пользовательский интерфейс ==>

    img

Чтобы завершить весь процесс, мы сделали почти то же самое, но без моста, теперь у нас может быть лучшая производительность, мы можем делать это синхронно и даже можем расставлять приоритеты синхронных операций в пользовательском интерфейсе. Время запуска также будет быстрее, а приложения будут меньше.

Итак, когда мы можем начать использовать эти вещи?

Вы можете следить за их соответствующими обновлениями на Github:

  1. JSI
  2. Fabric
  3. Turbo Modules
  4. Lean Core
  5. CodeGen

Само собой разумеется, что большая часть изменений будет завершена постепенно и, надеюсь, в четвертом квартале 2019 года или в первом квартале 2020 года.

Некоторые справочные документы для более глубокого понимания: