Как обернуть компонент React с небольшим штрафом за производительность?
Моя команда использует библиотеку React MaterialUI. Чтобы обеспечить согласованный шаблон пользовательского интерфейса и упростить настройку компонента MaterialUI, мы переносим каждый компонент MaterialUI в наш собственный компонент. Например:
const style = {} // our project custom style for ListItemText
const OurListItemText = ({primary, secondary, classes}: Props) => (
<MuiListItemText
primary={primary}
secondary={secondary}
className={classes.text}
/>
) // we only expose primary and secondary props of the original MuiListItemText.
// Team members are blocked from customising other MUIListItemText props
export default withStyles(styles)(OurListItemText)
MuiListItemText
- это оригинальный компонент MaterialUI, а OurListItemText
- наш компонент оболочки. В нашем проекте разрешено использовать только OurListItemText
.
В качестве фрагмента выше, OurListItemText
ничего не делает, кроме как перенаправить реквизиты в MuiListItemText
. Однако это сильно влияет на производительность:
ListItemText
в верхней части находится в OurListItemText
а ниже - MuiListItemText
. Если мы используем MuiListItemText
напрямую, это может быть на 50% быстрее (мы попытались), что заметно, когда у нас есть 100 ListItemText
. Удаление withStyles
HOC немного улучшается, но не значительно.
ListItemText
- только один пример, у нас есть аналогичная проблема с производительностью для других упакованных компонентов. (2 Typography
на графике выше - это еще одна пара нашего компонента-обертки и MUI-оригинал-компонента)
Как улучшить производительность этих простых компонентов реквизита-пересылки?
Ответы
Ответ 1
упаковка компонента React добавляет один дополнительный уровень полного жизненного цикла React (т.е. необходимо установить оболочку). Можно ли это избежать?
Вы можете избежать жизненных циклов, избегая JSX и напрямую вызывая функции.
Например.
{Component({ data: 1, children: 'Hello' })}
вместо
<Component data={1}>Hello</Component>
Это сообщение в блоге утверждало, что он улучшил скорость на 45% со своим тестовым случаем.
Однако этот синтаксис может быть не столь читабельным и понятным.
Некоторые цитаты из Дана Абрамова по этому вопросу:
Мы рассматриваем такие оптимизации, как это в контексте Prepack, но в ближайшие пару месяцев ничего не получится сразу же использовать. Через год или два у нас может быть что-то.
Обратите внимание: если вы не создаете тысячи элементов, разница в производительности не будет заметна. Кроме того, если ваши компоненты не очень плоские и простые, "чистая победа" от этой оптимизации, вероятно, будет гораздо менее актуальной на практике.
Я бы не стал дожидаться, пока Prepack сделает оптимизацию, хотя временная шкала неясна, и результирующая оптимизация может быть не такой.
Что касается значимости улучшения производительности, это будет зависеть от вашего проекта, и единственный способ быть уверенным в том, чтобы попробовать и увидеть улучшение для себя.
Ответ 2
Если вам нужна сырая производительность - не оберните ListItem, а напишите вместо этого свою замену
Источник элемента списка не имеет никаких дополнительных зависимостей, поэтому Ctrl-C, Ctrl-V будет работать
Затем отрегулируйте свои потребности, удалите код, который вам не нужен, и т.д....
Это гарантирует максимальную производительность
Отрицательная сторона - стоимость поддержки будет расти.