Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a performance difference between the sx prop and the makeStyles function in Material UI?

I've just started using Material UI, and I know that it uses CSS in JS way of styling components.
I saw 2 methods in the documentation of how to create styles:

Using the sx prop:

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

Using the makeStyles method:

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

I know that CSS in JS is much less performant than native CSS.
But between these 2 methods I just wrote, which one is more performant (if any)?

By the way, I'm using Material UI version 5, which claims to have better performance overall with emotion instead of JSS

like image 823
nil Avatar asked Jul 14 '21 17:07

nil


People also ask

What is the use of makeStyles in material UI?

makeStyles is a function from Material-UI that allows us to create CSS classes and rules using JavaScript objects. The makeStyles function returns a React hook that we can use in a functional component to access the styles and classes. Then, we can apply these styles to any element in our component.

How do you use a SX prop?

To use the sx prop, add the custom /** @jsxImportSource theme-ui */ pragma comment to the top of your module or configure automatic JSX runtime in your transpiler. The sx prop lets you add any valid CSS to an element, while using values from your theme to keep styles consistent.

Why are emotions over styled components?

The biggest advantage of Emotion is its easily handled object styles for writing CSS. Take, for example, the case of styled-components, wherein the developer must create unique names for different components, all while avoiding identical naming styles.


2 Answers

JSS is slightly faster than Emotion for static styles (i.e. styles that aren't dynamic based on props). JSS is much slower than Emotion for dynamic styles -- Emotion has similar performance for both static and dynamic styles.

You can find information about the performance difference for static styles between JSS and Emotion in the following issues:

  • https://github.com/mui-org/material-ui/issues/22342#issuecomment-696553225
  • https://github.com/mui-org/material-ui/pull/22173#issuecomment-673486269

JSS was about 10% faster than Emotion for static styles. For dynamic styles, JSS was 6 times slower than Emotion in one test the Material-UI team performed, and this is why JSS was eliminated from the list of possible styling engines for v5.

The documentation at https://next.material-ui.com/system/basics/#the-sx-prop contains the following performance information:

Benchmark case Code snippet Time normalized
a. Render 1,000 primitives <div className="…"> 100ms
b. Render 1,000 components <Div> 120ms
c. Render 1,000 styled components <StyledDiv> 160ms
d. Render 1,000 Box <Box sx={…}> 370ms

I would expect the performance of using Emotion directly (using either the styled approach or the css prop) to be similar to Benchmark case c. I would expect makeStyles for static styles to be slightly faster than that (in the 140ms to 150ms range), but not by much. You can see that the sx prop is notably slower, but keep in mind that the extra 200ms of overhead is for 1,000 elements so the additional overhead is still only one-fifth of a millisecond per component rendered. The amount of overhead added by the sx prop is dependent on how many CSS properties you pass to it. For a small number (< 5) of properties, the difference between styled and sx is not as significant as shown in the table above.

I don't recall seeing any claims by Material-UI that v5 is faster than v4 overall. v5 does add many new features that would have been hideously slow (due to leveraging dynamic styles) if implemented using JSS, so they were able to add those features while keeping the styling performance comparable to v4.

The biggest downside of using makeStyles with Material-UI v5 is that you would then be causing your users to download both JSS and Emotion as part of your bundle. If you have an existing application built with v4 that already uses makeStyles a lot (that you are now moving to v5), one migration option is tss-react which retains a similar syntax to makeStyles, but is backed by Emotion instead of JSS and has similar performance to the styled API. There is now a codemod for migrating JSS styles to tss-react.

Related answer: Why is the `sx` prop so much slower?

like image 77
Ryan Cogswell Avatar answered Oct 10 '22 12:10

Ryan Cogswell


I had the same problem, but then I decided to rebuild the makeStyles overall based on @emotion/css:

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

Basically you will need to make one custom hook useClasses, which will rework your theme => ({... function or styles object into classes, that are used exact the same way like with makeStyles.

There is also IMO a huge benefit of using this approach compared to the way how it is proposed in the mui codemod:

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

Because the emotion/css will cache same styles as one className, and you basically reuse classes, for example:

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

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

both styles1.someClass1 and styles2.someClass2 will have the same class name in production, e.g. css-1qs4g5r. I tryed it already. But in the mui proposed codemode-way you will have unique class names, which are not really reusable.

like image 2
bukso Avatar answered Oct 10 '22 14:10

bukso