Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Sass with CSS Modules & Webpack

I've been building a project for a while using Webpack, Sass, and CSS modules. Normally in my .scss files, I define a class like:

:local(.button) {     color: white; } 

and in my React components, in the render method, I require the styles:

render = () => {     const styles = require('./MyStyles.scss');     <div className={ styles.button } /> } 

and all is good with the world. Everything works as expected.

Now today I was reading through the CSS Modules page and noticed that none of the selectors were encompassed by :local() like mine and furthermore that they were importing the styles like:

import styles from './MyStyles.scss'; 

And I thought "Wow that looks much nicer, it's easier to see where it's imported, ect. And I'd love not to use :local() and just have things local by default." So I tried that and immediately ran into several problems.

1) `import styles from './MyStyles.scss';

Because I'm using ESLint on my React files, I immediately get an error thrown that MyStyles.scss doesn't have a default export which would normally make sense but the CSS Modules page stated:

When importing the CSS Module from a JS Module, it exports an object with all mappings from local names to global names.

so I naturally expected the default export of the stylesheet to be the object they're referring too.

2) I tried import { button } from './MyStyles.scss';

This passes linting but button logs as undefined.

3) If I revert to the require method of importing my styles, anything not specified with :local is undefined.

For reference, my webpack loader (I'm also including Node-Neat and Node-Bourbon, two awesome libraries):

{ test: /.(scss|css)$/, loader: 'style!css?sourceMap&localIdentName=[local]___[hash:base64:5]!resolve-url!sass?outputStyle=expanded&sourceMap&includePaths[]=' + encodeURIComponent(require('node-bourbon').includePaths) + '&includePaths[]=' + encodeURIComponent(require('node-neat').includePaths[1]) + '&includePaths[]=' + path.resolve(__dirname, '..', 'src/client/') } 

My questions, following all of this, are:

1) When using CSS Modules with Sass, am I confined to using either :local or :global?

2) Since I'm using webpack, does that also mean I can only require my styles?

like image 758
barndog Avatar asked Dec 23 '15 21:12

barndog


People also ask

Can you use Sass with CSS modules?

Yes, it is possible. You can make files with the extension ". module. scss" to use SCSS and CSS Module at the same time.

Can we use both CSS and SCSS in react?

Introduction: We can use SASS in React using a package called node-sass. Using node-sass we can just create sass files and use them as the normal CSS files in our React application and node-sass will take care of compiling sass files. Modules: To compile sass code, node-sass can be used.

Is Sass better than CSS?

SCSS contains all the features of CSS and contains more features that are not present in CSS which makes it a good choice for developers to use it. SCSS is full of advanced features. SCSS offers variables, you can shorten your code by using variables. It is a great advantage over conventional CSS.


1 Answers

Soon after posting, I figured out the solution. The problem, which I thought was quite confusing, was in my Webpack config. Originally my loader looked like:

loader: 'style!css?sourceMap&localIdentName=[local]___[hash:base64:5]!resolve-url!sass?outputStyle=expanded&sourceMap 

which enabled to me to 1) require my Sass and 2) wrap my styles in :local.

However, the css loader was missing the modules option so that it looked like:

loader: 'style!css?modules&sourceMap&localIdentName=[local]___[hash:base64:5]!resolve-url!sass?outputStyle=expanded&sourceMap 

Now I can import my styles and I don't have to wrap them in :local (although I presume I still can if I want to).

What I found most interesting about all this is that without the modules option, one can still use CSS Modules-esque features, although somewhat limiting.

EDIT:

Something I noticed, a future warning to whomever looks at this answer, is if you're using the eslint-plugin-import to lint the imports in your javascript code, it will throw an error upon importing styles like:

import styles from './MyStyles.scss'; 

because of the way CSS Modules exports the resulting styles object. That does mean you'll be required to do require('./MyStyles.scss') to bypass any warnings or errors.

like image 118
barndog Avatar answered Sep 23 '22 21:09

barndog