В этой статье я собираюсь глубоко погрузиться в мир React и рассказать о том, что является основным ценностным предложением React, что такое React Reconciler, как эта функция работала до версии 16 и как работает сегодня.

Что такое реконсиляция?

Прежде всего разберемся, что такое реконсиляция — в переводе это означает «действие по приведению одного взгляда или убеждения в соответствие с другим«.

В этом выражено основное предназначение самого React в контексте одностраничных приложений. Помните, как до появления SPA были проблемы из-за медленной маршрутизации и способа обработки браузерами переходов между страницами? Чтобы улучшить скорость перехода между страницами в браузерах, React представил новый способ обработки маршрутизации в веб-приложениях, и это была модель Virtual DOM.

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

Для достижения этой цели команда React представила Virtual DOM и Stack Reconciler (стековый согласователь/реконсилятор), чтобы обрабатывать виртуальное дерево DOM в памяти и затем применять изменения к реальной DOM декларативным способом.

Стековый реконсилятор и урок истории

Вернемся в прошлое, когда еще не были представлены хуки React, и посмотрим, как React строил DOM-деревья в то время.

Ниже показан упрощенный рабочий процесс React 15 и предыдущих версий React. В тех версиях был согласователь, называемый Stack Reconciler, который представлял собой структуру данных LIFO, отвечающую за выбор работы и возврат результатов подобно тому, как работает стек вызовов JavaScript.

React Stack Reconciler до версии 16

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

Для примера представим следующее взаимодействие пользователя с пользовательским интерфейсом:

Проблема неотзывчивого пользовательского интерфейса в стековом согласователе

Как видите, при синхронном и последовательном порядке работы стекового согласователя происходит следующее: если пользователь хочет набрать что-то в поле текстового ввода, ответ будет запаздывать, так как в порядке рендеринга установлен высокий приоритет; но мы никак не можем заставить стек обрабатывать эту операцию с более высоким приоритетом. Другая проблема заключается в том, что если в середине этого процесса произойдет какая-либо ошибка, мы не сможем узнать, где именно она произошла и какова трассировка стека, что может быть очень неприятно.

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

Fiber Reconciler — это то, что нам нужно

В версии React 16 и выше команда React представила новый способ обработки единиц работы и виртуального дерева DOM с помощью мета-функции Fiber Reconciler. Она предназначена для решения двух основных проблем:

1. Синхронный способ обработки единиц работы.

2. Приоритизация и параллельность выполнения единиц работы.

Текущая версия React Fiber Reconciler состоит из множества Fiber-узлов, которые представляют собой обычные объекты JavaScript с большим количеством свойств для обработки.

Fiber — это объект JavaScript с множеством свойств или единица работы.

Под Fiber Reconciler будем подразумевать текущую версию React Reconciler, основанную на объектах Fiber или единицах работы.

Что такое единица работы?

Единицей работы в React может быть изменение пропса, состояния или обновление DOM — все, что может изменить вывод на экран.

Fiber имеет отношение 1 к 1 с другими элементами, будь то экземпляр компонента, узел DOM и т. д. Типы хранятся в теге в объекте Fiber. Возможны следующие типы:

Варианты типов, которые могут находиться в отношении 1 к 1 с объектом Fiber

В исходном коде библиотеки React-DOM можно найти функции с такими названиями:

  • createFiberFromtText();
  • createFiberFromElement();
  • createFiberFromPortal();

Таким образом, Fiber’ы можно создать из множества опций DOM и экосистемы React. Теперь узнаем, как работает новая функция React Fiber Reconciler!

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

Ниже приведен простой пример страницы:

Пример DOM-дерева, которое нам нужно отобразить на экране

Теперь посмотрим, как с этим справляется React Fiber Reconciler:

Процесс реконсиляции React Fiber в упрощенном виде

Как видно на рисунке выше, React Fiber Reconciler строит дерево элементов DOM в памяти (Virtual DOM) и сохраняет копию реальной DOM, чтобы работать над реальной DOM и выводить обновления на виртуальную DOM, а затем применять эти изменения к реальной DOM.

Этот процесс состоит из двух этапов:

  1. фаза рендеринга (асинхронная);
  2. фаза фиксации (синхронная).

Когда в приложении происходит обновление, Fiber Reconciler начинает работу с помощью функции beginWork, которая принимает три параметра: текущее дерево, находящееся в реальной DOM, дерево текущей работы и лэйны рендеринга. Лэйн — 32-битное представление задачи во время реконсиляции.

На самом деле процесс намного сложнее. Посмотрим, что происходит «под капотом» в React Reconciler, когда нажимается кнопка и изменяется состояние.

  1. Когда пользователь нажмет на кнопку, процесс начнется с вызова функции beginWork(currentTree, workInProgressTree, лэйны), которая рекурсивно начнет проверять дерево сверху вниз, спускаясь к узлам-братьям и дочерним узлам.
  1. Пока есть работа, которая должна быть выполнена, то есть происходят изменения в пропсах или состояниях, узлы, нуждающиеся в обновлении, размечаются с помощью обновленного флага.
  1. По завершении работы над единицей Fiber отмечаются обновления и работа завершается вызовом функции completeWork(currentTree, workInProgressTree, лэйны), которая отвечает за переход вверх по рабочему дереву. 
  1. При завершении работы также строится дерево HTML-элементов, которое будет отображаться в реальной DOM на основе обновлений, происходящих в памяти и не отображающихся на экране.
  1. Когда Fiber заканчивает работу, он фиксирует все вновь построенные деревья DOM в реальной DOM и отражает изменения, которые будут показаны на экране.
Функция beginWork в библиотеке React-DOM
Функция completeWork в библиотеке React-DOM

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

Используя функцию Fiber Reconciler, мы можем применять одновременный рендеринг, приостанавливать функции и устанавливать границы ошибок, чтобы отлавливать ошибки на этапе рендеринга и показывать пользователю резервные копии, не допуская падения всего приложения сразу!

Как работают и как применяются эффекты в этом процессе?

Результат Fiber-дерева зависит не только от него самого. Есть множество эффектов, которые могут произойти, например сетевой запрос, мутация в реальной DOM, вызов методов жизненного цикла или все то, что происходит за пределами экосистемы React и должно быть синхронизировано с состоянием React.

На этапе фиксации React проходит по всем эффектам и применяет их к экземплярам компонентов, причем результаты видны пользователю. React делает все это за один проход.

Побочные эффекты React в процессе реконсиляции

Итак, мы узнали, что происходит «под капотом» React, а также разобрались в экосистеме React и в том, как она обрабатывает процессы и DOM.

Ресурсы:

Читайте также:

Читайте нас в Telegram, VK и Дзен


Перевод статьи Max Shahdoost: How does the React fiber reconciler work?

Предыдущая статьяPascal: ностальгическое путешествие сквозь годы и код
Следующая статьяАдаптируем Android-приложение к большим размерам экрана с помощью классов window-size