I have a minimal React component which consists of two files: button.jsx
and button.less
. The styles are imported and the class names are appended with a hash to make all styles local to the component.
This is great, but i'd like to have all component code in one file. Is it possible to inline the styles in jsx file without losing css modularity?
button.jsx
import React from 'react';
import styles from './button.less'
export default class Button extends React.Component {
render() {
return <button className={styles.primary}>{this.props.text}</button>;
}
}
button.less
@import '~semantic-ui/src/definitions/elements/button.less';
.common {
composes: ui button;
}
.primary {
composes: common primary;
}
webpack.config.js (relevant bits)
module: {
loaders: [
{
test: /\.jsx$/,
loader: 'babel'
},
{
test: /\.less$/,
loader: "style!css?modules&importLoaders=1!less"
}
]
},
button.jsx
<style lang="less" modules>
@import '~semantic-ui/src/definitions/elements/button.less';
.common {
composes: ui button;
}
.primary {
composes: common primary;
}
</style>
import React from 'react';
export default class Button extends React.Component {
render() {
return <button className={styles.primary}>{this.props.text}</button>;
}
}
Inspired by vue.js and vue-loader.
I believe this is a duplicate of this unanswered question: Using css-loader inline with Webpack + React
I wrote a Webpack loader for this very purpose:
https://github.com/chrisdavies/stylextract-loader
It allows you to write a single style tag per JSX file and it supports webpack CSS modules, too, if you want.
At build time, it extracts the rules from your style tag and moves them out to an external CSS file.
I should note that because it simply extracts your rules out to an external CSS file, it plays nice with SASS, autoprefixer, etc
You can use callback-loader for this. This is actualy a workaround, but it do the trick. Just implement a callback which will extract your css-code and replace it with appropriate import. For example:
webpack.config.js
var fs = require('fs');
var cssIndex = 0;
// Do not forget to create and clean temporary folder "cssTemp" before
var webpackConfig = {
...
resolve: {
alias: {
cssTemp: path.resolve('./cssTemp')
}
},
module: {
loaders: [
{ test: /\.jsx$/, loader: "callback!babel" }
]
},
callbackLoader: {
cssCallback: function(code) {
var filename = cssIndex + '.less';
cssIndex++;
// Save the css code from the callback argument
fs.writeFileSync('./cssTemp/' + filename, code);
// Return the import statement which will replace the callback statement
return 'import styles from "cssTemp/' + filename + '";';
}
}
...
};
button.jsx
import React from 'react';
cssCallback(`
@import '~semantic-ui/src/definitions/elements/button.less';
.common {
composes: ui button;
}
.primary {
composes: common primary;
}
`);
export default class Button extends React.Component {
render() {
return <button className={styles.primary}>{this.props.text}</button>;
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With