Sass with CSS Modules & Webpack
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.
Related videos on Youtube
Comments
-
barndog almost 4 years
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?-
zedd45 about 8 yearsI would escape the wildcard (
.
) character in your loader'stest
property, like so:test: /\.(scss|css)$/
-
-
Luke Willis over 6 yearsWhen using eslint-plugin-import, you can ignore your scss files specifically. see: npmjs.com/package/eslint-plugin-import#importignore