I'm using nwb to create isolated React components. Some of these components require CSS styling.
How can I import an scss stylesheet while developing, and how can I package it for production during the build process?
Thanks!
I've not made any reusable components which depend on a stylesheet preprocessor before, so I don't know the best way to go about this - pointers to projects which have this kind of build set up would be welcome :smile_cat:
Looking at some other libraries I've used before.
dist/ dir containing compiled CSS, with less/ and scss/ dirs if you want to use a preprocessor.dist/ dir containing compiled CSS, with lib/less/ dirs if you want to use a preprocessor.I wonder if you can have a stylesheet as an entry module in Webpack.
That would be one approach to setting up a style build, if so.
Neither of these require styles directly from components - I'm wondering what a build setup for that looks like.
The only project I have which includes its own styles is react-octicon, which publishes a css/ dir and uses require('../css/Octicon.css') to avoid having to do any sort of CSS build, as that will resolve successfully from src/ and lib/.
Currently, if you require CSS from a component, nwb's UMD build will generate a main.css bundle under umd/. This is pretty much by accident - I only noticed it when I checked out the umd/ dir which gets published for react-gridforms.
Using webpack the best way to go about this would probably be to use a loader chain such as style!css!sass for your .scss imports which would allow you to simply import and use the styles within your React components in the following manner:
import styles from './button.scss';
export default props => <button className={styles.button} />
Here are the respective loaders:
The style-loader will handle hot-loading during development and bundling the outputted styles (these get compiled into your component module) at production build time.
Bonus: I would _strongly_ recommend using the
modulesoption for thecss-loaderso that you ensure your CSS is correctly scoped and will _never_ clash with external code.
The most flexibility for an end consumer of your component would be to provide a way to optionally pass different classes to use for various parts of your public component. This would require you to distribute your CSS separately rather than bundled in your component module (you can do this at build time with the extract-text-webpac-plugin) and leave the loading/styling strategy up to the end user. For more on this I'd recommend reading around react-themeable.
@hackingbeauty has a component we can use as a test case for React component projects which import their own style and also use a CSS preprocessor:
Possibly some useful information in webpack/webpack#170
Thanks @Chrisui - nwb already has a pipeline set up for CSS loading which is also capable of chaining on any CSS preprocessors it finds installed in nwb-* packages - this issue is more about how we can deal with extracting that CSS when building a React component to publish to npm, so people using components with nwb don't have to set up a webpack config, or tweak their own to handle CSS preprocessing for dependencies.
Did anybody ever figure out how to import a css file in a js file such that it is build by webpack and included in the lib?
@insin I have a library with multiple components that source their own .css files. I just ran the build and published it to find that it seems the app only pulled in what I have in the main src/index.js file - nothing outside of that. In dev mode, it works like a charm - only production destroys it.
Is there a way to fix this? We have around 1k downloads thus far and we have a major update that we just posted.
Here's the repo for you to dig into. All the components are located in src/modules:
https://github.com/whiplashmerch/whiplash-ui-library
Thanks for addressing this so quick @insin 馃憤
@caseybaggz Did you solve this issue? I'm attempting to build a similar UI lib, but I can't get the style include working. I added the whiplash ui lib, but the styles are missing as well. How do you use it in production?
My solution was to use node-sass-chokidar + npm-run-all instead of nwb-sass.
I put my SCSS in /src/styles/src, and updated my package.json to automatically generate importable .css files:
"scripts": {
"start": "npm-run-all -p watch-css start-js",
"start-js": "nwb serve-react-demo",
"build": "npm-run-all build-css build-js",
"build-css": "node-sass-chokidar src/styles/src -o src/styles",
"build-js": "nwb build-react-component --copy-files",
"watch-css": "npm run build-css && node-sass-chokidar src/styles/src -o src/styles --watch --recursive",
},
"devDependencies": {
"node-sass-chokidar": "^0.0.3",
"npm-run-all": "^4.1.2",
"nwb": "0.21.x",
"react": "^16.2.0",
"react-dom": "^16.2.0",
},
Simply run yarn start or yarn build as normal.
You can now import CSS files directly with no hassle, even though you just edit the SCSS files:
// Spinner.js
import React from 'react'
import styles from './styles/spinner.css' // spinner.css available in ES/lib/UMD builds!
Most helpful comment
Using webpack the best way to go about this would probably be to use a loader chain such as
style!css!sassfor your.scssimports which would allow you to simply import and use the styles within your React components in the following manner:Here are the respective loaders:
The
style-loaderwill handle hot-loading during development and bundling the outputted styles (these get compiled into your component module) at production build time.Going a step further...
The most flexibility for an end consumer of your component would be to provide a way to optionally pass different classes to use for various parts of your public component. This would require you to distribute your CSS separately rather than bundled in your component module (you can do this at build time with the extract-text-webpac-plugin) and leave the loading/styling strategy up to the end user. For more on this I'd recommend reading around react-themeable.