@emotion/core vs vanilla emotion
See original GitHub issueUPDATE: I published final writeup on this topic here. tl;dr I think vanilla emotion
is a better option for the majority of React projects: https://vriad.com/blog/emotion-core-vs-vanilla-emotion
I’m a huge fan of the emotion
module but am somewhat bewildered by some of the tradeoffs made in the design of @emotion/core
.
I wrote up some thoughts as a blog post but haven’t published them yet. I want to give the Emotion team some time to respond to my criticisms. I don’t want to put publish a post that misrepresents this package or its design goals. It’s very possible I simply don’t understand some of the use cases you were optimizing for. Here’s a link to a Gist containing the text of my post: https://gist.github.com/vriad/23956586223e36931718399c0caa2eef
I’d hugely appreciate anyone who can shed some light on these decisions for me.
I absolutely love vanilla emotion
which is why I’m sad to see it getting deprioritized in favor of core. I say this in the post but it’s worth repeating: I love Emotion and I’m hugely indebted to your guys for all your great work!
Issue Analytics
- State:
- Created 3 years ago
- Reactions:7
- Comments:9 (4 by maintainers)
Top GitHub Comments
Just a note - we understand how this name is confusing and we are in the process of renaming this package to
@emotion/react
. It will be published as such when v11 gets released.Well, truth to be told - this is the preferred way of using
@emotion/core
. It doesn’t require any additional configs and it works with the majority of the community tooling. It also makes it explicit for code readers that a particular file is using custom “createElement” instead of the regular one. For beginners, or just when exploring a different codebase, this might actually be seen as a positive thing - it’s inclusive.I don’t agree with this statement - you have to only add this import if you are using
jsx
. In the very same way that you need to import React when you are using regular JSX - it only might be less of a pain because you often have React already in the scope anyway.Note: this part might change in the future though as React has introduced automatic transform recently (https://github.com/babel/babel/pull/11154), we are waiting for the support for it to get released in React itself and for it also being supported by TypeScript team which is on their roadmap (from what I believe).
The goal is to provide predictable styling - we can only do that if we control the styling, thus this actually helps us ensure that you are using emotion-generated styles. Otherwise, you can find yourself in the middle of specificity wars once again.
This really sounds very aggressive and out of place. Even if a little bit quirky render props are still valid for some use cases and this is one of them (at least for us). I’m actively thinking about a different API for this but it has to work with 0 config SSR and that’s not an easy feat for this feature. We don’t believe this is much of an issue because you rarely should use non-emotion styles (ideally you wouldn’t have to use them at all).
Many people are tired of configuring things. The configuration also spills itself on all of the consumers. Emotion is used, sort of, as an engine for multiple other libraries, and with 0config approach they don’t have to educate their consumers (who might not even be aware of using Emotion under the hood) that they need to setup something for SSR. It just works.
Well - it’s not our responsibility to document how to integrate Emotion with all of the fancy meta frameworks. We understand that we could maybe give guidance on how to integrate with the most popular ones, but there are already dedicated packages for this, so not sure why we should bother duplicating efforts. If you feel that their docs are lacking something you can always try to improve them by providing helpful PR. Also - those packages are only needed if you want to do something custom. 0config approach is, well, 0 config so it doesn’t require any extra documentation. That’s why we recommend it - we don’t have to integrate in any special way with any other tool, things should just work if you stick to the 0 config approach. The time we can spare on the project is also not infinite, so we don’t feel like documenting the stuff we don’t really recommend.
I believe many would disagree and you also sound very aggressive here which I don’t find to be OK. However, we agree that builtin theming is not needed, there is an open PR which we’d like to revive with arguments laid out against it: https://github.com/emotion-js/emotion/pull/973/files . We’ve found out that people like the builtin theming though, so we are keeping it - but we plan to emphasize that there is a better way of doing things in v11 docs.
Because we don’t give you string class names back, but rather just opaque objects, the rule insertion is lazy. This might not be as interesting on its own, but it allows us to customize injection through a
<CacheProvider>
. Use cases for this are not as common - but they exist and once you ever come across one then you might be very thankful for the path we’ve chosen because otherwise re-implementing stuff to accommodate new requirements could be very hard. With vanilla Emotion to customize this stuff, you need to create a custom instance and use it everywhere. Main things that can be customized:This allows libraries built on top of Emotion don’t care about this stuff because, if needed, the final consumer can decide about this stuff.
If the chosen tradeoffs are not for you then you are welcome to continue using vanilla Emotion. We don’t plan to remove the support for it.
@Andarist I really appreciate all this feedback! I want to apologize for the tone - it was far too aggressive in all the cases you mentioned. I got a little carried away. I certainly won’t publish this until that’s been corrected.
I’ll admit upfront I haven’t been following the API updates coming in v11 - I’ll look more deeply into that.
I agree that
jsx
is invalidThere’s a lot I don’t understand about the use cases you’re optimizing for. Frankly I hope I never encounter a scenario that necessitates the use of
CacheProvider
😅! Sounds hard.I don’t understand how the
css
prop makes styling more predictable than vanilla Emotion. Is there a resource you can direct me to that explains that a bit more? Or am I misreading that?My primary source of my frustration is something that I only briefly alluded to in my writeup: the documentation explicitly steers people to
@emotion/core
overemotion
, yet for a majority of casesemotion
is the better choice. With core:css
prop breaks portability/encapsulation (one of the core philosophical pillars of React)cx
It seems like all of these tradeoffs were made in the name of zero-config SSR, which isn’t a consideration for a hefty majority of React-based SPAs.
My recommendation would be to make these tradeoffs more explicit in a documentation, and two present these approaches as two equally valid options (instead of explicitly recommending core for React projects). Based on npm downloads, it’s clear that
emotion
has plateaued in usage in the last 18 months, whereas core has tripled. I suspect in a majority of cases the developer would have been better served by vanilla, but didn’t think to go against the officially recommended route. If that developer found Emotion via NPM or this repo’s README, they may not even know about the existence of the vanilla option - it’s not mentioned anywhere.You should know that all of my thoughts are colored by the fact that I LOVE
cx
. My whole approach to styling is dependent on the composition of many small utility classes. Getting rid of simple, markup-freecx
usage in favor of zero-config SSR isn’t a tradeoff I agree with (and that’s okay!). But the fact that vanilla/cx
aren’t the “recommended” approach (and are therefore hugely underutilized) makes me a little sad.Thanks again for your feedback. I’ll let you know if I decide this post is worth publishing. And great work - seriously.