streamich / nano-css

Distilled CSS-in-JS for gourmet developers
The Unlicense
426 stars 24 forks source link

Extract: add ability to replace calls to nano with generated classnames #185

Closed TheBosZ closed 6 years ago

TheBosZ commented 6 years ago

I'm very excited by this project; it ticks a lot of the needs we have for a CSS-in-JS solution.

One thing would make it fit exactly: the ability to not have a runtime at all.

I know that goes against some of the CSS-in-JS "rules".

The way I would see it would be that I could use the sheet interface to add classes to my components. Then I could run an extract that would generate the CSS file. This would also replace the references to the classes with the actual class names.

It could be like this: It would replace the calls to nano with the results Input:

const cssMap = {
    input: {
        border: '1px solid grey',
    },
    button: {
        border: '1px solid red',
        color: 'red',
    }
};
const styles = sheet(cssMap);

<input className={styles.input}>
<button className={styles.button}>Click me!</button>

And output:

const styles = {
    input: 'class-b-1px-solid-grey',
    button: 'class-b-1-px-solid-grey-c-red',
};

<input className={styles.input}>
<button className={styles.button}>Click me!</button>

This way, the actual calls to nano would be removed and then pruned. The size of my app wouldn't be any bigger, but it would have the advantages of CSS-in-JS except for dynamic classes/styles, which is a known limitation and one which I accept.

streamich commented 6 years ago

You could do it now by placing your style into a separate file, like app.styles.js:

exports.styles = nano.sheet({
    input: {
        border: '1px solid grey',
    },
    button: {
        border: '1px solid red',
        color: 'red',
    }
});

And then when you evaluate those styles, you could generate another file with only class names:

const styles = require('./app.styles.js').styles;
fs.writeFileSync('app.classes.js', `export const classes = ${JSON.stringify(styles)};`);

And in your app you include .classes.js file which only has classes.

import {classes} from './app.classes.js';

Alternatively, you could write a Webpack loader that does it for you.

TheBosZ commented 6 years ago

Putting them in a separate file and doing it that way seems viable.

I'm not smart enough to write a webpack loader (we use Rollup, but same thing), but maybe I'll try to figure out how to do it.

Thanks for your input!

TheBosZ commented 6 years ago

I have a super hacky basic plugin that does exactly what I want: https://bitbucket.org/TheBosZ/rollup-plugin-nano-css

Thanks for your great project, I can't wait to start using it!