mui / material-ui

Material UI: Comprehensive React component library that implements Google's Material Design. Free forever.
https://mui.com/material-ui/
MIT License
93.4k stars 32.15k forks source link

[system] Support new style engine that generates static CSS files at build time #34826

Closed oalexdoda closed 3 weeks ago

oalexdoda commented 1 year ago

(issue heavily edited by @oliviertassinari)

Summary 💡

I recently found an article that breaks down in detail why CSS-in-JS doesn't have the best performance https://dev.to/srmagura/why-were-breaking-up-wiht-css-in-js-4g9b. One of the core features I'm using with MUI is the sx / Emotion / CSS-in-JS feature.

This is a proposal to provide a new style engine inspired by the zero-runtime CSS-in-JS libraries: extract all the CSS-in-JS, split it into CSS modules when building the app for production, and serve the styles that way instead. The goal is to retain as much as possible of the current API while having no runtime.

There should be as few breaking changes as possible, and provide a progressive migration story. We wouldn't deprecate the other style engines.

Examples 🌈

Motivation 🔦

The current CSS-in-JS runtimes:

  1. takes more CPU cycles to add the styles than raw CSS would take.
  2. increases bundle size
  3. are not compatible with react server component https://github.com/emotion-js/emotion/issues/2928 https://github.com/styled-components/styled-components/issues/3856 and might never be https://github.com/mui/material-ui/issues/34905#issuecomment-1330939826 #35993
  4. don't work well with Next.js v13

We have seen developers use Tailwind CSS because they are afraid that Material UI is not fast enough. But by moving, they get, what we could argue is a poorer DX with the utility CSS class name. The problems a. you unlearn CSS with utility classes, b. the utility classes are harder to use for conditional styling.

Also, this example shows that it's all about the perception of performance and not the actual performance. Having no runtime would make it very clear that the performance should "logically" be equivalent.

What success looks like?

Two ways to quantify success in this effort:

Benchmarks

oalexdoda commented 1 year ago

Some ideas:

Any way to get something like this in MUI natively?

oliviertassinari commented 1 year ago

It would be awesome to move to a static extraction styled() API. I'm adding it as a feature candidate for Material UI v6: #30660.

The biggest challenges would likely be:

  1. How to deliver the same great DX?
  2. How to make the amount of breaking changes acceptable? We should keep most of the existing API and make it a progressive migration.

The solution could be to make this runtime-less a "mode". Meaning something that developers can progressively migrate to. Typically when they want to benefit from RSC (#35993).


Other ideas:

The end goal is to get points c. and d. as close as possible to a.

Screenshot 2022-10-30 at 23 26 28

https://mui.com/system/getting-started/usage/#performance-tradeoffs.

To be fair, d. seems good enough in most cases. It's usually not good enough when you have a large DOM, at which point, you need to rewrite a bit how the styles are applied, which costs you time.

If you open https://pagespeed.web.dev/report?url=https%3A%2F%2Fmui.com%2F&form_factor=mobile, it's not "insanely great" as would say Steve Jobs, this would likely help.

Plus, Server-side React Component could help a lot, for which, we need MUI System to be compatible with #35993. Success would like having 100/100 in:

Screenshot 2023-03-30 at 15 39 05

https://pagespeed.web.dev/analysis/https-mui-com/z9cmpqb6ka?form_factor=desktop

saad12035 commented 1 year ago

@altechzilla I would recommend that instead of using sx with the components create a separate file and use makestyles for HTML semantics and styled for MUI components. In this way you can reuse a styled component in anywhere in your project instead of redefining it and it also helps in a way that with every reload of the page your inline styling will not be rendered and you can always apply lazy loading on the components which are less important.

mnajdova commented 1 year ago

I think that exploring https://github.com/cristianbote/goober could also be great, it could already yield a great improvement see the benchmark https://twind.dev/handbook/introduction.html#benchmarks.

Agree, I remember we discussed this in the past, maybe even trying with a custom styled-engine adapter to be optionally added (and if it proves to be success we can promote this adapter as a default). I could try to create a dirty poc soon about this.

We could also rewrite the MUI System implementation, it's slower than it needs to be.

👍 we could actually start investigating this in Q1 2023

Another idea would be to use a utility classes for the sx prop, meaning we can keep the same object syntax, but transform each key value pair to a utility class. We are likely going to need to drop some of the functionality it has but it could be a start. Developers can then also use the className prop instead of sx. I remember we started investigating this two years ago, but from what I remember back then we didn't pursue with it because developers would need to load additional css in their project statically.

oliviertassinari commented 1 year ago

Goober was explored a bit in https://github.com/mui/material-ui/pull/27776

mnajdova commented 1 year ago

Goober was explored a bit in https://github.com/mui/material-ui/pull/27776

Thanks for linking it, I will check to see what was missing

oalexdoda commented 1 year ago

Kinda wish Emotion was optional to some degree to avoid complexity and issues like: https://github.com/mui/material-ui/issues/34910 https://github.com/vercel/turbo/discussions/2312#discussioncomment-3966587

dohomi commented 1 year ago

It would be great if MUI styles would rely entirely on css class composition (as mentioned in https://github.com/mui/material-ui/issues/34826#issuecomment-1291693785), similar like DaisyUI build with Tailwind. That could power different themes like Material UI, Joy UI customised with different CSSVars

ryanelian commented 1 year ago

I agree with @altechzilla and @dohomi

In fact, it would be ideal if MUI is tightly integrated with Tailwind and can be configured as Tailwind CSS plugin.

On the MUI side, Tailwind CSS class composition can be used to develop internally.

On the End-User side, not only it is simpler to add Tailwind plugin in Next.js (unlike integrating with Emotion), but we can also get IntelliSense in Visual Studio Code when using the Tailwind CSS IntelliSense extension:

image

This allows MUI to expose CSS class names which can be used to decorate plain HTML elements as alternative to writing with React component. For example:

<Alert severity="error">This is an error alert — check it out!</Alert>

can be

<div className="alert alert-error">This is an error alert — check it out!</div>
zoy-l commented 1 year ago

hi self-recommendation, I implemented one, if needed I can transfer this library to mui styils🤠

gijsbotje commented 1 year ago

I believe @stitches/react would also be a good option. Haven't worked with it, but if I read the introduction correctly it does almost everything emotion does but with better SSR support.

oliviertassinari commented 1 year ago

@gijsbotje I think that Material UI needs static CSS extraction, so not stitches, e.g. https://github.com/nextui-org/nextui/discussions/1035

gijsbotje commented 1 year ago

@gijsbotje I think that Material UI needs static CSS extraction, so not stitches, e.g. https://github.com/nextui-org/nextui/discussions/1035

Yeah upon further reading it looked like it wasn't maintaned very well.

karlhorky commented 1 year ago

Seems like Chakra UI (another UI library dependent on Emotion) is going to switch away from Emotion and to a zero runtime CSS-in-JS solution called Panda:

Zero runtime CSS-in-JS [Panda]

This is the most common and most challenging request we get from users.

Runtime CSS-in-JS and style props are powerful features that allow developers to build dynamic UI components that are composable, predictable, and easy to use. However, it comes at the cost of performance and runtime.

With the release of React Server Components, providing the ability to write Chakra UI components on the server has become crucial. This is a huge win for performance, development, and user experience.

We're building a new, framework-agnostic styling solution that keeps most of the great features of Chakra's styling system but extracts styles at build time. It'll also feature a PostCSS plugin that extracts styles at postcss run time during development.

Panda will leverage new modern platform features like CSS variables, cascade layers, and W3C token spec.

https://www.adebayosegun.com/blog/the-future-of-chakra-ui

🤔 Wonder if it would make sense to combine efforts between MUI and Chakra UI...

raskyer commented 1 year ago

https://github.com/chakra-ui/panda https://panda-css.com/

Panda has been released couple days ago and look a lot like what we need for MUI.

arobert93 commented 1 year ago

Moving to panda-css appears to be a good strategy, but considering the existence of projects utilizing the styled and sx syntax, what impact will it have on the developer experience (DX)?

It would be beneficial to have a script in place that converts the current approach or an internal backwards compatibility mechanism, enabling the translation of the existing styled and sx syntax into panda-css syntax. Alternatively, introducing a distinct styling utility called css while deprecating the other methods could be another solution.

It is important for developers to be aware that this package is currently in alpha, and there may be potential breaking changes.

oalexdoda commented 1 year ago

I think if anything happens to sx there should absolutely be a codemod that updates everything automatically and a very thorough migration guide. We have thousands of components that would require updating and it would be impossible to update everything manually.

A codemod which would have to work for scenarios where sx is composed dynamically (i.e. with conditionals, spread objects, etc.), and all the different ways MUI uses it.

tihuan commented 1 year ago

Panda is working on supporting styled syntax:

https://github.com/chakra-ui/panda/discussions/808#discussioncomment-6263046

noherczeg commented 1 year ago

Panda is working on supporting styled syntax:

chakra-ui/panda#808 (comment)

https://github.com/chakra-ui/panda/pull/786 has been merged.

jeremytenjo commented 1 year ago

I think if anything happens to sx there should absolutely be a codemod that updates everything automatically and a very thorough migration guide. We have thousands of components that would require updating and it would be impossible to update everything manually.

A codemod which would have to work for scenarios where sx is composed dynamically (i.e. with conditionals, spread objects, etc.), and all the different ways MUI uses it.

Ideally the sx prop will work the same but use panda css under the hood.

paales commented 1 year ago

Seen this? https://stylex-docusaurus.vercel.app/docs/

foxyblocks commented 10 months ago

@altechzilla and @arobert93

Panda supports the same API as emotion (except that the sx prop has been renamed to css, but is otherwise equivalent)

You can still use the styled(...) factory function as you could with emotion:

CleanShot 2023-11-08 at 13 17 08@2x

colmtuite commented 10 months ago

StyleX has been delayed for a long time but it seems like they're close to releasing it now, so that would probably get my vote. It seems to tick all the boxes:

  1. Collocation.
  2. Type-safe.
  3. Zero runtime.
  4. Variant support (a la Stitches).
  5. Supported by Meta, so it may become the "default React styling lib".
  6. Authored by people with decades of styling architecture experience.

My only gripe is that the DX seems to be a little awkward in places, like named imports for variables and some verbose syntax. But this gripe would be very minor for me personally.

Overall, it seems to be a great fit for MUI. Here's an apt quote from the docs.

For years, we have had to choose between "Design System" components that come with styles baked in but can be difficult to customize or "Headless" components that are completely unstyled. StyleX finally lets you build UI components that can have default styles and still be customizable.

https://stylex-docusaurus.vercel.app/docs/learn/thinking-in-stylex/

o-alexandrov commented 10 months ago

It seems MUI explores a possibility of using stylex in this Reddit thread IMG_4725

romgrk commented 10 months ago

@o-alexandrov I explored a bit stylex but after reviewing the design documents produced by Brijesh who's been leading the effort, I have mixed feelings about arguing for it. The main issue I see is that it would be much harder to preserve compatibility of MUI by using stylex. I will agree that having a styling engine that is not MUI specific would be great. The fact that it's backed by meta is a strong argument as it can lead to a big adoption through the react ecosystem. But yeah I don't think I'll argue for it at this point.

We have an internal notion doc that summarizes the pros/cons of other style engines, if someone with access to it can publish it it could help understand the decision.

abriginets commented 9 months ago

Is there any progress on this or at least a consensus? Many developers including myself are very excited about RSC but cannot proceed with them due to MUI components being forcefully SSR'ed. I would really appreciate it if I could track progress and get involved in discussions or development.

mbrookes commented 9 months ago

@brijeshb42 it would be good if you could reply to @abriginets. I could generalise about why our zero runtime solution is a better fit, but it would be better coming from the race-horses mouth. 🙂

mbrookes commented 9 months ago

I think if anything happens to sx there should absolutely be a codemod that updates everything automatically and a very thorough migration guide. We have thousands of components that would require updating and it would be impossible to update everything manually.

As the author of a good chunk of the codemods for the last major (with significant contribution and refinement from others of course) I can assure you that we won't deviate from that path. It always surprises me when people ignore the tools provided, and then complain about how hard the migration was, but if we don't provide them, then the critique will be valid.

That said, we should also try to minimise the amount of breaking changes, and perhaps more frequent majors area way to achieve that by spreading the load.

brijeshb42 commented 9 months ago

TLDR - it's not possible with the current API surface of stylex.

As @romgrk pointed out, until styled provides customization at build time level for library authors, it won't be possible to integrate it with our libraries. And even if we are somehow able to do it, it will be a completely different API, thus breaking stuff for our users, especially styled function and sx prop. Having said that, we are anyways working on our own zero runtime library where we are right now testing out perf gains and ironing out the end-user API. If in future, if stylex allows the types of customization that we want, we can experiment with abstracting it's usage inside our zero runtime library itself while still providing users with somewhat similar APIs that are there right now.

o-alexandrov commented 9 months ago

Btw, today, Meta finally open sourced stylex:

DiegoAndai commented 3 weeks ago

Material UI v6 is now stable and supports static CSS extraction via Pigment CSS. Thanks for participating in the discussion. We hope you can try Pigment CSS out and provide feedback. I am closing this issue.

github-actions[bot] commented 3 weeks ago

This issue has been closed. If you have a similar problem but not exactly the same, please open a new issue. Now, if you have additional information related to this issue or things that could help future readers, feel free to leave a comment.

[!NOTE] We value your feedback @oalexdoda! How was your experience with our support team? If you could spare a moment, we'd love to hear your thoughts in this brief Support Satisfaction survey. Your insights help us improve!