Search code examples
javascriptreactjswebpackpostcsscss-modules

How to use scss with css modules / postcss inside components


I'm failing to figure out how to setup my webpack in order to be able and use scss modules inside my components like:

import styles from './ComponentStyles.scss'

So far I tried configuring webpack to use sass-loader alongside postcss-loader but had no luck:

  {
    test: /\.scss$/,
    loaders: [
      'isomorphic-style-loader',
      'css-loader?modules&localIdentName=[name]_[local]_[hash:base64:3]',
      'postcss-loader',
      'scss-loader'
    ]
  }

Note isomorphic-style-loader is a library I use instead of style-loader due to server rendering requirements, in its github page docs they actually use postcss-loader with .scss extension, but in my case scss is not compiled if I follow their example.


Solution

  • I had to do some tinkering myself, but eventually landed on the following

    package.json

    "autoprefixer": "^6.3.1",
    "css-loader": "^0.23.1",
    "extract-text-webpack-plugin": "^1.0.1",
    "node-sass": "^3.8.0",
    "sass-loader": "^3.1.2",
    "style-loader": "^0.13.0"
    

    webpack config

    ...
    const autoprefixer = require('autoprefixer');
    const ExtractTextPlugin = require('extract-text-webpack-plugin');
    const autoprefixer = require('autoprefixer');
    ...
    
    const config = {
        ...
        postcss: [
            autoprefixer({
                browsers: ['last 2 versions']
            })
        ],
        plugins: [
            new ExtractTextPlugin('css/bundle.css'),
        ],
        module: {
            loaders: [
                {
                    test: /\.scss$/,
                    loader: ExtractTextPlugin.extract('style', 'css!postcss!sass')
                }
            ]
        }
        ...
    };
    

    bootstrap.jsx

    import React from 'react';
    import ReactDOM from 'react-dom';
    import App from './app';
    import style from './scss/style.scss';
    
    ReactDOM.render(
        <App/>,
        document.getElementById('my-app')
    );
    

    For those interested: what's happening here is bootstrap.jsx is the webpack entry point, and by importing our raw scss file (via relative path), we tell webpack to include it during the build process.

    Also, since we've specified a loader for this file extension in our configuration (.scss), webpack is able to parse style.scss and run it through the defined loaders from right to left: sass --> post-css --> css.

    We then use extract-text-webpack-plugin to pull the compiled CSS out from bundle.js, where it would normally reside, and place it in a location (css/bundle.css) relative to our output directory.

    Also, using extract-text-webpack-plugin is optional here, as it will simply extract your CSS from bundle.js and plop it in a separate file, which is nice if you utilize server-side rendering, but I also found it helpful during debugging, since I had a specific output location for the scss I was interested in compiling.

    If you're looking to see this in action, here's a small boilerplate that uses it: https://github.com/mikechabot/react-boilerplate