developit / microbundle

📦 Zero-configuration bundler for tiny modules.
https://npm.im/microbundle
MIT License
8.06k stars 361 forks source link

CSS inject in style tag #833

Closed karthikcodes6 closed 2 years ago

karthikcodes6 commented 3 years ago

Is there any way to inject the CSS in a style tag instead of generating a separate CSS file?

developit commented 3 years ago

This would require inlining the CSS into JavaScript as a string, which is bad.

rschristian commented 3 years ago

While I'm not going to try to justify the practice, if you do really need to do it, react-colorful does this and is a decent example of doing that with React. This was only done as there was a very vocal group of users who apparently hated the idea of using a CSS loader in their apps as they went all-in with CSS-in-JS.

microbundle can be ran with --css inline, and you can inject into the head in a fashion similar to what's shown here: https://github.com/omgovich/react-colorful/blob/master/src/hooks/useStyleSheet.ts

rake7h commented 3 years ago

@developit i see inject is false for postcss, can we have an option in cli to make it true? I believe making inject:true will inject the CSS into head by default.

https://github.com/developit/microbundle/blob/master/src/index.js#L470

rschristian commented 3 years ago

@rake7h That doesn't really make sense in the context of Microbundle. It doesn't handle HTML, so there is no <head> at build time.

Edit: was corrected, didn't know about style-inject

rake7h commented 3 years ago

@rschristianinject:true is useful for react libraries with css import (import './style.css'). It basically uses the style-inject to inline the CSS instead of generating an external CSS file on dist. There are uses cases where some React + CSS library want to inline the styles in bundle itself instead of generating the external css file.

I see on react-colorful, they are manually adding the style tags, which I feel can be completely off loaded to bundler(rollup-plugin-postcss) through inject:true option.

rschristian commented 3 years ago

@rake7h Hm, you can already support that use case with css --inline. It won't create an external CSS file either.

As style-inject is super tiny and this practice should really be avoided (react-colorful doesn't have a great reason to be doing this either, IMO, but it's what we ended up falling back to), I personally don't think another CLI option is justified. Microbundle already tries to avoid doing much with CSS.

I'm pretty happy to keep the process of manually handling that as a good "Are you sure you want to be doing this?" message. If you really wanted to copy/paste style-inject, it's just 23 lines (not including references or license notices).

rake7h commented 3 years ago

@rschristian Thanks, I got the point that Microbundle is avoiding css related stuff. But could you tell me why we are calling inlining CSS in JS is a bad practice or should be avoided?

rschristian commented 3 years ago

@developit knows far more about this than I likely ever will, he might be able to point out some good resources. Alex Russel has a blog post talking about mobile perf, which goes into this a bit. Not sure of any other good resources off the top of my head.

The short of it is that CSS and JS have very different costs of usage. They are not equals, and by inlining CSS into JS, you're paying the heavy JS price when that could be entirely avoided.

Might also be worth mentioning that the inlining approach means your consumers lose all control over the widget. Can't pass inlined CSS strings through a proper asset pipeline. This is only an issue if you're distributing for general use of course.

rschristian commented 2 years ago

Closing this out, as I think it's been addressed.