В соавторстве с Peng Dong, Ozair Ghulam, Christina Or, Khanh Bui

Содержание

  • Обзор
  • Этап примирения
  • Фиксация фазы
  • Прохождение

Чтобы демистифицировать Reactime, нам сначала нужно понять, как один из его механизмов работает с React под капотом, концепция, называемая React Fiber. React состоит из двух фаз: фазы согласования и фазы фиксации.

Этап согласования

На этапе согласования, когда React обновляет DOM браузера, React создает отдельный файбер (обратите внимание, строчная буква «f» файбера с прописным F не относится к отдельным объектам файбера, файберы просто объекты JavaScript) для каждого узла Дерево DOM или элемент React. При первом рендеринге приложения создается дерево волокон на основе каждого из элементов React, а также других факторов. Это дерево волокон создается в виде связанного списка, в котором свойствами являются return, child и siblings дочернего элемента. Возврат с путями к волокнам ссылается на родителя. Каждое волокно представляет собой единицу работы, и когда волокна, составляющие связанный список, завершают свою работу, они используют «ключ» для рекурсивного возврата к родительскому узлу.

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

React Fiber делит работу на более мелкие блоки для каждого волокна, позволяя сосредоточить работу только на узлах с изменениями. Отдельные узлы волокна имеют 4 примечательные рабочие функции. Теперь, когда работа разделена на отдельные волокна, React Fiber устанавливает различные приоритеты задач для единиц работы со следующим ранжированием от самого высокого до самого низкого приоритета: синхронные действия, задачи, анимация, действия с высоким приоритетом, действия с низким приоритетом и действия вне экрана. Например, при поиске пользователя в Твиттере мы ожидаем, что страница загрузит информацию о его профиле в качестве задачи с более высоким приоритетом перед загрузкой его изображений и сообщений. При предыдущей реализации реконсилера, пока стек задач не был завершен, запросы приложений задерживались. Однако React Fiber работает асинхронно, поэтому можно создавать новые запросы и изменения, чтобы приоритизировать эти запросы с более высоким приоритетом по мере выполнения других задач.

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

В процессе обхода дерева волокон существуют четыре соответствующие функции работы, которые мы будем обсуждать ниже: CompleteWork, beginWork,completeUnitOfWork и PerformUnitOfWork. beginWork запускается, начиная с корневого узла, и проходит по дереву. Он постоянно проверяет, есть ли какие-либо ожидающие работы, и если нет изменений или ожидающих работ, то эти узлы волокна пропускаются. Это позволяет React Fiber перемещаться по дереву и выполнять работу только с узлами, для которых есть работа/обновления, которые необходимо выполнить. BeginWork зависит от тега, связанного с каждым узлом волокна, который будет выполнять соответствующую функцию для обновленияузла. Функция beginWork будет возвращать дочерние волокна до тех пор, пока не останется дочерних, и она не достигнет конечного узла, где она вернет null. Другая рабочая функция, PerformUnitOfWork, также будет вызывать дочерние волокна, пока не достигнет конца дерева, после чего PerformUnitOfWork вызывает функцию CompleteUnitOfWork.

Фаза фиксации

Когда вся работа над деревом завершена, React готов перейти к заключительному этапу, известному как этап фиксации, где завершенные изменения отображаются в пользовательском интерфейсе. Обратите внимание, что эта часть является синхронной, в отличие от фазы асинхронного рендеринга. Единственным исключением для фазы синхронного рендеринга является первая загрузка DOM. Отсюда, имея в виду текущее дерево и дерево НЗП из более ранней фазы, дерево НЗП помечается как завершенная работа. Кроме того, теперь существует список эффектов, который содержит список выбранных волокон, которые были обновлены. На данный момент изменяются только определенные узлы и элементы React, поэтому необходимо обновить только эти элементы. React Fiber создаст связанный список изменений, известных как побочные эффекты, которые необходимо выполнить, что значительно улучшит оптимизацию, позволив фазе фиксации сосредоточиться только на элементах, которые имеют изменение, и он может получить доступ к этой информации в формате связанный список. Узел, представляющий список эффектов, также будет иметь точку с именем nextEffect, пока вызывается функция completeRoot.

Пошаговый рабочий процесс

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

Как только начнется фаза рендеринга, React снова пройдет по дереву волокон, выполнив функцию beginWork (как объяснялось ранее) и завершив работу в узлах волокон, обозначенных для выполнения работы. Когда фаза рендеринга завершается, начинается фаза фиксации, и, как упоминалось ранее, эта фаза не может быть разделена на пакеты работ и является синхронной. Результатом этапа рендеринга является список эффектов и готовое дерево работы. Список эффектов представляет собой связанный список выбранных узлов, ожидающих обновления, удаления или добавления на этапе фиксации, в то время как дерево finishWork содержит информацию, ожидающую применения обновлений к пользовательскому интерфейсу приложения.

Наконец, в фазе фиксации есть 2 подэтапа. First React выполнит все манипуляции с DOM, такие как удаление и вставка для готового рабочего дерева, и назначит готовое рабочее дерево текущим деревом. Теперь, когда дерево обновлено, вы можете использовать методы жизненного цикла, такие как componentDidMount, в обновленном дереве. Эти функции и другие детали процесса волокна можно изучить более подробно, перейдя по ссылкам ниже.

Дальнейшее чтение: