material-ui icon indicating copy to clipboard operation
material-ui copied to clipboard

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

Open oalexdoda opened this issue 1 year ago • 30 comments

(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 🌈

  • https://vanilla-extract.style/
  • https://linaria.dev/
  • https://compiledcssinjs.com/

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:

  • Runtime. Use the benchmark in https://github.com/mui/material-ui/issues/21657#issuecomment-707140999. We should aim toward another x3 to x8 in the runtime of MUI System v6 compared to v5 (when v5 was ~x3 faster than v4).

  • Bundlesize. Material UI with emotion + its client-side components + its theme adds ~25k gzipped of JavaScript vs. Tailwind CSS.

    • Tailwind CSS with the app directory and a simple page: https://github.com/vercel/next.js/tree/canary/examples/with-tailwindcss: 80.8 kB gzipped
    • Material UI with the pages directory and a simple page: https://github.com/mui/material-ui/tree/master/examples/material-next 104 kB gzipped

Benchmarks

  • https://cakepop-docs.vercel.app/pop/usage, using https://github.com/wayfair/rainbow-sprinkles behind the scene.

oalexdoda avatar Oct 19 '22 11:10 oalexdoda