awesome-everything EN
↑ Обратно к восхождению

Браузер и фронтенд-рантайм

Что делает реконсилер: render vs commit

Суть React делит каждое обновление на прерываемую фазу render, вычисляющую дифф, и атомарную фазу commit, применяющую мутации DOM — именно в зазоре между ними живут и выигрыши производительности, и баги.
Высота — путь к senior
НольJuniorMiddleSenior
Ты на junior-высоте — поверхность
◷ 10 min

Вы вызываете setState. Где-то между этим вызовом и сменой пикселя на экране React решил, какие компоненты перезапустить, сравнил два дерева, вычислил минимальный набор мутаций DOM и применил их — возможно, остановившись на полпути, чтобы пропустить нажатие клавиши. Машина, которая это делает, — fiber-реконсилер.

Что делает реконсилер. Когда ваши данные меняются, React вычисляет наименьший набор изменений страницы, совпадающий с новыми данными, и применяет только их. DOM медленно мутировать — тронуть его тысячу раз намного медленнее, чем тронуть десять. Вся работа React — вычислить десять реальных изменений вместо слепого повтора тысячи.

Метафора чертежа. Наивный строитель снёс бы дом и отстроил с нуля при каждом изменении чертежа. React — умный строитель: он держит текущий чертёж приколотым к стене, рисует новый на втором листе, кладёт два рядом и отмечает только различия. Потом он шлёт бригаде один наряд работ ровно с этими изменениями. Рисование второго чертежа — фаза render; передача наряда бригаде — фаза commit.

Почему две фазы. React делит каждое обновление на две фазы. Фаза render обходит дерево компонентов, запускает функциональные компоненты и строит новое дерево узлов fiber — эта фаза чистая, не производит видимых изменений и с React 18 может быть приостановлена, возобновлена или выброшена. Фаза commit берёт готовое новое дерево и применяет мутации DOM одним синхронным, непрерываемым взрывом. Всё хорошее и всё опасное в производительности React живёт в зазоре между «прерываемым render» и «атомарным commit».

setState → экран
ФАЗА RENDERПерезапуск компонентов · построение fiber-дерева · дифф← прерываема
ФАЗА COMMITПрименение мутаций DOM · запуск эффектов · отрисовка← атомарна, не прерывается

Антон · Браузер печатает в поле поиска, фильтрующем длинный список. Дима · Origin-сервер комментирует: «Каждое нажатие — это изменение состояния. React перезапускает компоненты, строит новое fiber-дерево, диффит его против текущего. Список из 800 строк изменился — но React находит только 12 строк, которые реально отличаются, и мутирует только эти 12 DOM-узлов. Остальные 788 не тронуты. Поэтому поле всё ещё ощущается мгновенным».

Расставь шаги по порядку

Вызов setState проходит через React к экрану. Расставьте шаги по порядку.

  1. 1 Вызван setState — React планирует обновление
  2. 2 Фаза render: перезапуск компонентов, построение нового fiber-дерева
  3. 3 Реконсиляция: дифф нового дерева против текущего
  4. 4 Фаза commit: применение мутаций DOM одним взрывом
  5. 5 Браузер рисует изменённые пиксели
Викторина

Почему React диффит два дерева вместо того, чтобы просто переписать весь DOM?

Викторина

Какую фазу React может приостановить на полпути?

Закончи аналогию

В метафоре строителя React держит текущий чертёж приколотым к стене и рисует новый на втором листе, чтобы их сравнить. Удержание двух версий дерева сразу — одной показанной, одной строящейся — называется как?

Посчитай

Планировщик React делает render-работу маленькими кусками, потом уступает браузеру. Примерно сколько миллисекунд один кусок, прежде чем React проверяет, не пора ли уступить?

мс
Числа реконсилера React
Срез до shouldYield()
~5 мс
Сложность реконсиляции
O(n) (эвристика)
Сложность наивного дифф-дерева
O(n³)
Ширина битовой маски lane
31 lane
Фаза commit
Атомарна, не sliceable
Сравнение bailout
Object.is на props
Вспомните перед уходом
  1. 01
    Почему фазу render можно прервать, а фазу commit — нет?
  2. 02
    Что такое двойная буферизация в React?
  3. 03
    Примерно сколько длится один render-срез React, прежде чем он проверяет shouldYield()?
Итог

Реконсилер React делит каждое обновление на фазу render (прерываема, чистая, строит новое fiber-дерево в памяти) и фазу commit (атомарна, синхронна, применяет мутации DOM). Фаза render может быть приостановлена и возобновлена, потому что не производит видимых изменений; фаза commit не может, потому что мутирует DOM и должна оставить страницу в согласованном состоянии. React использует двойную буферизацию — два дерева одновременно — чтобы обновление в процессе никогда не было видно. Планировщик нарезает render-работу на ~5 мс кусков и уступает браузеру между ними, сохраняя отзывчивость страницы даже при большом перерендеривании.

Связанные уроки
встречается в143
Продолжить восхождение ↑Объект fiber и дерево с двойной буферизацией
хоткеи развернуть
поиск
K
пред. пьеса
k
след. пьеса
j
тиры
t
это меню
?
sources3
expand
  1. 01
  2. 02
  3. 03

Trademarks belong to their respective owners. Editorial reference only.