developit / microbundle

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

react + css module not generated #922

Closed daniele-zurico closed 2 years ago

daniele-zurico commented 2 years ago

Hi everyone, I'm using microbundle for my react+typescript project but I realized when I try to bundle it the classes are not applied to my components. This is an example:

import React from 'react';
import style from './toggle.module.css';

the folder structure is:

/component
  --> Toggle.tsx
 --> toggle.module.css

In my package.json I've:

"scripts": {
    "build": "microbundle --jsx React.createElement --css-modules true",

When I import my component I can see: Screenshot 2022-01-04 at 15 51 52

However, my toggle doesn't have the CSS applied correctly and looks like a normal input.

What I'm doing wrong?

rschristian commented 2 years ago

Microbundle will export a stylesheet, have you remembered to import it?

import style from './toggle.module.css'; isn't valid JS, so it will not exist in the JS bundles that Microbundle creates. You'll need to make sure to import the CSS when you go to consume your component.

daniele-zurico commented 2 years ago

sorry @rschristian I'm confused...

This is my Toggle.tsx component:

import React from 'react';
import style from './toggle.module.css';

export const Toggle = () => <div className={style.switch}/>

which part is not correct?

rschristian commented 2 years ago

No worries.

Just to make sure we're on the same page, Toggle.tsx is built by Microbundle, correct? If so, how are you consuming it, i.e., using it in an app?

As import '<something>.css' isn't actually valid, and is special syntax handled by bundlers, so Microbundle strips that from the output. That import won't exist in your output JS. A correct usage could then be:

import { Toggle } from 'my-toggle-lib';
import 'my-toggle-lib/style.css';
daniele-zurico commented 2 years ago

oh no no... is not what I'm doing. My library is creating the Toggle component with his own style pre-defined so the app that will use it will have directly the component already styled. example:

export const Toggle = () =>

this library is bundled and packaged as npm module

- myAPP

```tsx
import "Toggle" from "myLibrary";
function App() {
return (
    <Toggle/>
)
}
rschristian commented 2 years ago

My library is creating the Toggle component with his own style pre-defined so the app that will use it will have directly the component already styled.

That's not possible to do, as there is no standardized way to import non-JS and distribute it on NPM or the like. Therefore Microbundle strips out the import style from './toggle.module.css'; from your builds, to ensure you're distributing working output for all platforms. You'll always need to import the stylesheet separately.

See https://github.com/developit/microbundle/issues/416 for more of information on this.

You'll need to alter your consumption to the following:

import "Toggle" from "myLibrary";
import "myLibrary/style.css";
function App() {
return (
    <Toggle/>
)
}
daniele-zurico commented 2 years ago

woah I didn't expect that. It honestly looks really weird because all the components library have the embedded style to use... bootstrap, material etc you don't import the css but is bundled inside the component itself

rschristian commented 2 years ago

Most of those are using various CSS-in-JS solutions which come at a pretty significant cost, but yes, you get to avoid the difficulties of importing/working with non-JS.

daniele-zurico commented 2 years ago

and with microbundle I don't have any way to do that?

rschristian commented 2 years ago

Do what, use CSS-in-JS libraries instead of CSS? Sure, as far as I'm aware there's nothing stopping you. I've gotten styled-components to work before.

You can also inline the CSS file into JS, but would really suggest avoiding this.

// with `microbundle --css inline`:
import css from './foo.css';
console.log(css); // the generated minified stylesheet

react-colorful needed this, and you can see how we ended up implementing it here

daniele-zurico commented 2 years ago

so I've a way to extend the microbundle rollup configuration so I can use stuff like rollup-plugin-postcss?

rschristian commented 2 years ago

You do not have a way to extend or alter the rollup configuration beyond the documented options, no. Microbundle aims to be zero config, so there's limited ways to interact with it.

Not sure how that's related to CSS-in-JS or inlining CSS through our options though, so I'm a tad confused.

daniele-zurico commented 2 years ago

how I can then bring a css-in-js library that allows me to bundle the css module in my library directly? Inlining css is not a solution for me because it will create more problems.

rschristian commented 2 years ago

CSS-in-JS is another styling paradigm altogether, you don't bundle CSS files into your library with them. Goober is an example of such a tool.

Most of those component libraries you mentioned don't use CSS files. That's how they avoid requiring users to import them. They create styles in a fundamentally different fashion. React-Bootstrap does, however, and has the exact same restriction that I'm talking about here.

If you want to author in CSS modules, you will need to import the stylesheet separately. There's no way around that.

daniele-zurico commented 2 years ago

Ok I'll upate my documentation that users need to include the css file then. THanks a lot for your time