Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Open
oalexdoda opened this issue Oct 19, 2022 · 30 comments
Assignees
Labels
enhancement This is not a bug, nor a new feature package: pigment-css Specific to @pigment-css/* package: styled-engine Specific to @mui/styled-engine package: system Specific to @mui/system performance

Comments

@oalexdoda
Copy link

oalexdoda commented Oct 19, 2022

(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 Plans to support Next.js 13 - /app directory emotion-js/emotion#2928 Nextjs 13 styled-components/styled-components#3856 and might never be Improve Next.js support #34905 (comment) Add React Server Component support for Layout components (Grid, Stack, Container) #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 oalexdoda added the status: waiting for maintainer These issues haven't been looked at yet by a maintainer label Oct 19, 2022
@oalexdoda

This comment was marked as resolved.

@oliviertassinari
Copy link
Member

oliviertassinari commented Oct 19, 2022

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

@zannager zannager added package: system Specific to @mui/system package: styled-engine Specific to @mui/styled-engine performance labels Oct 20, 2022
@saad12035
Copy link

@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
Copy link
Member

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.

@mnajdova mnajdova added discussion and removed status: waiting for maintainer These issues haven't been looked at yet by a maintainer labels Oct 26, 2022
@oliviertassinari

This comment was marked as resolved.

@mnajdova

This comment was marked as resolved.

@oalexdoda
Copy link
Author

Kinda wish Emotion was optional to some degree to avoid complexity and issues like:
#34910
vercel/turbo#2312 (comment)

@dohomi
Copy link
Contributor

dohomi commented Oct 31, 2022

It would be great if MUI styles would rely entirely on css class composition (as mentioned in #34826 (comment)), similar like DaisyUI build with Tailwind. That could power different themes like Material UI, Joy UI customised with different CSSVars

@ryanelian
Copy link

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
Copy link
Contributor

zoy-l commented Nov 15, 2022

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

@oliviertassinari oliviertassinari changed the title CSS-in-JS Performance Concerns - (sx) Add new style engine that generate static CSS files at build time Jan 30, 2023
@oliviertassinari oliviertassinari added new feature New feature or request waiting for 👍 Waiting for upvotes enhancement This is not a bug, nor a new feature and removed new feature New feature or request discussion labels Jan 30, 2023
@gijsbotje
Copy link
Contributor

gijsbotje commented Jan 31, 2023

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
Copy link
Member

oliviertassinari commented Feb 5, 2023

@gijsbotje I think that Material UI needs static CSS extraction, so not stitches, e.g. nextui-org/nextui#1035

@gijsbotje
Copy link
Contributor

@gijsbotje I think that Material UI needs static CSS extraction, so not stitches, e.g. nextui-org/nextui#1035

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

@karlhorky
Copy link

karlhorky commented Apr 13, 2023

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...

@oalexdoda oalexdoda changed the title Add new style engine that generate static CSS files at build time Add new style engine that generates static CSS files at build time May 6, 2023
@raskyer

This comment was marked as resolved.

@arobert93
Copy link

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
Copy link
Author

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

This comment was marked as resolved.

@noherczeg

This comment was marked as resolved.

@jeremytenjo

This comment was marked as resolved.

@paales
Copy link
Contributor

paales commented Sep 19, 2023

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

@foxyblocks
Copy link

@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
Copy link
Contributor

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

This comment was marked as outdated.

@romgrk
Copy link
Contributor

romgrk commented Nov 25, 2023

@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
Copy link
Contributor

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
Copy link
Member

mbrookes commented Dec 6, 2023

@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
Copy link
Member

mbrookes commented Dec 6, 2023

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
Copy link
Contributor

brijeshb42 commented Dec 6, 2023

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
Copy link

Btw, today, Meta finally open sourced stylex:

@oliviertassinari oliviertassinari changed the title Add new style engine that generates static CSS files at build time [system] Support new style engine that generates static CSS files at build time Feb 26, 2024
@oliviertassinari oliviertassinari added the package: pigment-css Specific to @pigment-css/* label Mar 10, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement This is not a bug, nor a new feature package: pigment-css Specific to @pigment-css/* package: styled-engine Specific to @mui/styled-engine package: system Specific to @mui/system performance
Projects
None yet
Development

No branches or pull requests