Emotion: Support atomic output

Created on 29 May 2020  ·  3Comments  ·  Source: emotion-js/emotion

Hey; we're using emotion and really like it. The object styles, jsx css attribute, etc. are great.

Out of curiosity, we've also seen things like the Facebook xstyles and Fela do basically what emotion does, but have atomic output, i.e. 1 rule per generated CSS class.

This is perhaps naive, but would/could/should emotion output that style of output? Either in a future version or as a config flag?

Granted, you're the experts, so perhaps this would be a bad idea? Or negligible in terms of performance / size of output / etc.? Or maybe it breaks common CSS patterns in obvious ways I'm missing/not thinking of?

Realistically the shop I'm at now is not Facebook :-) so it probably doesn't matter for us / most of us, but I'm/we're just wondering about it because naively the "1 rule per CSS class" seems like it would mean less styles injected into the browser/etc.

Fwiw I searched the docs/issue tracker and didn't see anything other than #63 from ~few years ago. This might be a good FAQ entry for others like me/us that are wondering the same "should emotion do atomic output? Is that 'better'?".

(I suppose pedantically emotion does do atomic output at the level of a unique/distinct set of rules, i.e. it'll reuse a class for the same ~N sets of rules, which is great, I guess I'm meaning atomic as in "literally just 1 (ish?) rule per class".)

Thanks!

discussion feature request

Most helpful comment

I hope you won't run into perf problems with Emotion - we try our best to make it fast 🏎️

All 3 comments

Well - this would require extra runtime/resolving code and we would have to figure out how to avoid mismatches between SSR and the client. Im afraid this is just out of the scope for emotion right now - we don't plan to support different "modes" (unless you would figure out how to do this without adding bundlesize). From our perspective, it doesn't matter much for emotion as we don't support external stylesheet extraction (and we don't plan to) - so if you are just using Emotion on the client then it completely doesn't matter as you don't really ship anything extra. For SSR it could yield some benefits but ultimately we just recommend SSRing "critical" content and you shouldn't have too many styles there so its cheaper for us to just render in a way we do and avoid conversion to atomic rules (and resolving conflicting rules!) as that would inquire slower rendering.

I hope this answers the original question 😅

@Andarist great! I think that makes sense.

You're right, we have no intent to do stylesheet extraction. And right, since we're doing it client-side, atomic-per-declaration (fela/stylex) or atomic-per-declaration-set (emotion/MUI/etc) wouldn't change our download size.

We were thinking it should reduce the number of generated classes that have to be insertRule'd into the DOM/style tags/CSSStyleSheet, by a "it would _probably_ make a difference?" amount.

Admittedly/as context, we got burned by MUI's CSS-in-JS style implementation which (for "dynamic" styles that pass props to the useStyles hooks, i.e. marginBottom: ${props.whatever}) does _not_ cache this "rule set of N rules --> generated class name", so when we used our custom MUI component in a tight loop (i.e. for every row in our table, for every column in the row, use this custom component that calls useStyles with a prop), it injected something like ~30,000 style elements (that had literally the same rules inside them) and was just a nightmare for performance (locked our page load for ~30 seconds).

Granted, we've since been slowly migrating to emotion, which handles this "style rule based on a prop" case really well, because even if a rule-set is prop-based, it can tell a class name for a given combination of those post-prop specific values already exists, and reuses it (and we're also just trying to use that pattern less). Which is great.

But anyway, that's just why we're skiddish about "number of injected style tags/ class names", even if it doesn't technically reduce download since. I.e. once marginBottom: 6px has been injected into a style tag just once, literally every other usage of that rule will use that class name, which naively "seems better".

That said, understood it sounds like the bookkeeping to do this within emotion is not free either, and I also admittedly don't really understand the nuances of things like resolving conflicts.

And, right, we've been pleased with emotion's performance so far anyway, so this initial question was just thinking-out-loud musing.

Thanks for answering it, I appreciate it!

I hope you won't run into perf problems with Emotion - we try our best to make it fast 🏎️

Was this page helpful?
0 / 5 - 0 ratings