reactjs 为什么sx prop 慢得多?

prdp8dxp  于 2023-05-28  发布在  React
关注(0)|答案(1)|浏览(167)

根据MUI自己的doco和this answer-使用sx的组件渲染速度明显慢于使用其他样式机制的组件。
从表面上看,sx看起来只是一个替代的方便API,用于做同样的事情--所以我不希望它有如此不同的性能配置文件。
我的问题是:* 为什么 * 使用sx渲染组件会慢得多-它有什么不同?这是一个完全不同的造型引擎还是什么?
我很好奇优化它的可能性,或者想出一个折衷方案,保留大部分的可用性,但省略任何导致速度减慢的功能。
请注意,这个问题是关于“为什么性能如此不同”-而不是“为什么你认为差异不重要”。

20jt8wwn

20jt8wwn1#

当我开始深入研究时,我意识到我需要测量不同场景的性能,以便对我对sx prop的性能方面的理解有信心。
MUI文档中的性能信息是使用基准测试收集的,可以在这里找到:https://github.com/mui/material-ui/tree/v5.13.2/benchmark/browser
我相信这些基准测试的早期版本是基于这个存储库的一些变体:react-native-web repo被用作起点,因为它的“基准”包包含一个有用的框架,用于测量不同React元素渲染/样式化方法的性能。
我在这里创建了自己的版本:https://github.com/ryancogswell/mui-style-benchmarks。您可以将此作为进一步深入研究的起点。下面是我的测量结果和结论。

我的“Mount deep tree”Benchmark结果

该测试呈现了639个元素,每个元素具有大约17个CSS属性,除了减少CSS属性数量以显示性能影响的情况(“..._minimal”,“..._medium”)。
| 样式化实现|时间(ms)|实施说明|
| - -----|- -----|- -----|
| 内联样式|二十二点七八|没有样式引擎,只使用style prop|
| mui_sx_full|三十六点八九|MUI Box sx prop with 17 CSS properties|
| 多sx介质|二十四点零九分|带有9个CSS属性的MUI Box sx prop |
| 多sx极小|十八点十五分|带有4个CSS属性的MUI Box sx prop |
| 多样式盒|二十二点三八|MUI styled带有17个CSS属性的MUI Box|
| mui_styled_box_minimal|十七块九|MUI styled带有4个CSS属性的MUI Box|
| tss_react_makestyles|十七点十分|makeStyles来自tss-react,带有17个CSS属性|
| 多样式|十六点九三|带有17个CSS属性的MUI styleddiv|
| 多样式极小|十三点七七|带有4个CSS属性的MUI styleddiv|
| 情感风格|十六点六九|Emotion styleddiv带有17个CSS属性|
| 情感风格简约|12.76| Emotion styleddiv带有4个CSS属性|
| 情感_css|十二点五十八|Emotion cssdiv带有17个CSS属性|

结论

  • MUI styled(例如import {styled} from '@mui/material/styles')只会给Emotion的styled增加少量开销。
  • tss-react的执行方式与MUI styled类似。
  • Emotion styled、Emotion css、MUI styled和MUI sx prop在传递给样式引擎的CSS属性越多时开销越大。
  • sx prop的性能比styled API下降得更快,因为传递给它的CSS属性更多。使用17个CSS属性,性能比styled API(2x)差得多。
  • sx prop在小范围内表现良好(例如:< 5)的CSS属性。特别是,如果您已经在给定的情况下使用MUI组件,那么使用styled Package 它或使用sx prop(如果您只是使用少量CSS属性)之间没有任何有意义的性能差异。

sx prop 变慢的原因是什么?

这是一个完全不同的造型引擎还是什么?
它不是一个不同的样式引擎。为sx prop所做的工作的输出被馈送到主样式引擎的styled API中(例如:情感或风格化-成分);因此,将sx prop与Box组件一起使用肯定会比在div上使用styled的等效样式慢,因为sx prop最终仍使用styled,但会先执行额外的工作。

sx prop额外做了什么工作?
  • MUI styled API调用styleFunctionSx,以便将sx prop中的CSS属性转换为样式引擎所期望的形式。
  • styleFunctionSx遍历sx属性中的所有CSS属性
  • 对于每个CSS属性,它都会检查是否有用于转换prop值的样式函数。这些样式函数为某些属性(如填充和边距)提供了速记符号支持,并支持使用主题间距单位代替像素值。
  • 每个样式函数都利用https://github.com/mui/material-ui/blob/v5.5.3/packages/mui-system/src/style.js中的样式函数来处理一些常见的prop值转换,包括对特定于断点的值的支持。

实际效果是,对于每个CSS属性,都有许多查找和函数调用,以查看是否需要转换CSS属性,即使在值传递而没有更改的情况下。
我很好奇优化它的可能性,或者想出一个折衷方案,保留大部分的可用性,但省略任何导致速度减慢的功能。

我确信sx prop 的性能改进是可能的,但我不认为有任何一个银可以轻松地使它更快。相反,它可能需要大量的小变化,每一个变化都几乎无法衡量,但累积起来会带来相当大的改善。挑战是在不同时使代码更复杂和/或更难维护和/或更容易出错的情况下进行这些更改。
“保留大部分可用性”的主要妥协是直接使用Emotion的css prop。它可以以与sx prop类似的方式直接在元素上使用--只是失去了sx prop提供的速记符号和主题查找。主题查找(例如对于颜色或间距单位)很容易通过使用组件中的useTheme hook直接从主题中获得。可以使用theme. API代替断点简写;尽管从DX的Angular 来看,sx断点特性要好得多。
我个人的方法是对大多数样式使用tss-react(这允许从基于JSS的makeStyles/useStyles直接迁移,同时从v4迁移到v5),然后对某些只在给定页面上出现少量次数的组件使用sx

相关问题