在Material UI中,sx prop和makeStyles函数之间是否存在性能差异?

21

我刚开始使用Material UI,知道它使用CSS in JS的方式来样式化组件。
在文档中有2种方法可以创建样式:

第一种方法是使用sx属性:

<Box sx={{ backgroundColor: 'green' }}/>

使用makeStyles方法:

makeStyles({
  root: {
    backgroundColor: 'green'
  }
})

我知道在JS中使用CSS比本地CSS性能要差得多。
但是在我刚刚写的这两种方法之间,哪一种更具性能优势(如果有的话)?

顺便说一下,我正在使用Material UI版本5,声称使用情感(emotion)而不是JSS可以获得更好的整体性能。

2个回答

27

JSS比Emotion在静态样式(即不基于props动态的样式)方面略快。但是,对于动态样式,JSS比Emotion慢得多——对于静态和动态样式,Emotion的性能相似。

您可以在以下问题中找到关于JSS和Emotion之间静态样式性能差异的信息:

JSS在静态样式方面比Emotion快约10%。在动态样式方面,根据Material-UI团队进行的一项测试,JSS比Emotion慢了6倍,这就是为什么JSS从v5的可能样式引擎列表中被淘汰的原因。 https://next.material-ui.com/system/basics/#the-sx-prop上的文档包含以下性能信息: | 基准测试案例 | 代码片段 | 时间规范化 | | ------------ | -------- | ---------- | | a. 渲染1,000个基本元素 | `
` | 100ms | | b. 渲染1,000个组件 | `
` | 120ms | | c. 渲染1,000个带样式组件 | `` | 160ms | | d. 渲染1,000个Box | `` | 370ms |
我预计直接使用Emotion(使用styled方法css属性)的性能类似于基准测试案例 c 。我预计对于静态样式,makeStyles的性能略高(在140ms至150ms范围内),但差别不大。您可以看到,sx属性明显较慢,但请记住,额外的200ms开销是针对1,000个元素的,因此每个渲染的组件仅增加了五分之一毫秒的额外开销。sx属性添加的开销量取决于您传递给它多少个CSS属性。对于少量(<5)属性,styledsx之间的差异不像上表中所示那样显着。

我不记得Material-UI声称v5整体比v4更快。v5添加了许多新功能,如果使用JSS实现会非常慢(由于利用动态样式),因此他们能够在保持样式性能与v4相当的同时添加这些功能。

使用Material-UI v5的makeStyles最大的缺点是会导致用户下载JSS和Emotion作为你的包的一部分。如果您已经使用了很多makeStyles构建了基于v4的现有应用程序(现在正在将其移动到v5),则可以选择tss-react进行迁移,它保留了类似于makeStyles的语法,但由Emotion支持,性能与styled API相似。现在有一个codemod用于将JSS样式迁移到tss-react

相关答案:为什么`sx`属性要慢得多?


1
@TwoHorses 是的,在v5中,您可以通过@material-ui/styles包(https://next.material-ui.com/guides/migration-v4/#material-ui-core-styles)使用它,但它被认为是不推荐使用的。 sx属性只是一个方便的实用程序,用于为Material-UI组件设置样式,但您仍然可以通过任何其他样式解决方案提供CSS类。 - Ryan Cogswell
2
@hotpink sx 被所有 MUI 组件支持,不仅仅是 Box。 - Ryan Cogswell
1
@NearHuscarl 我不认为我会说你应该“小心使用” sx,主要是我会避免在页面上呈现大量元素的组件中使用它。我不会担心页面上有100个或更少的元素使用 sx,但我可能会避免在列表项、网格或表格单元格、菜单项和其他高容量元素中使用它。 - Ryan Cogswell
就动态styled性能而言,只要函数没有执行任何昂贵的操作,它与传递样式对象时的性能不会有明显的区别。 - Ryan Cogswell
1
我们最近将一个应用程序从v4迁移到了v5,将所有样式移动到了sx。然后我们的构建时间变慢了10倍,IDE也变得非常缓慢。我们发现某种方式下,sx似乎对类型检查器造成了问题。在将所有样式从sx迁移到使用emotion css的className之后,我们恢复了正常。 - platzhersh
显示剩余5条评论

2

我曾经遇到过同样的问题,但后来我决定基于@emotion/css重新构建整个makeStyles:

https://dev.to/atonchev/material-ui-5-the-easiest-way-to-migrate-from-makestyles-to-emotion-1i9l

基本上,你需要创建一个自定义hook useClasses,它将重构您的theme => ({...函数或样式对象为类,这些类与使用makeStyles完全相同。

与mui codemod中提出的方式相比,我认为这种方法有一个巨大的优势:

https://github.com/mui-org/material-ui/blob/v5.0.0-beta.2/packages/material-ui-codemod/README.md#jss-to-styled

因为emotion/css会将相同的样式缓存为一个className,并且您可以基本上重用这些类,例如:

const styles1 ={
  someClass1: { color: 'black' }
}

const styles2 ={
  someClass2: { color: 'black' }
}

在生产环境中,styles1.someClass1styles2.someClass2都会有相同的类名,例如css-1qs4g5r。我已经尝试过了。但是在mui提出的代码模式下,您将拥有唯一的类名,这些类名实际上并不可重用。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接