Matthew Matthew - 2 months ago 21
React JSX Question

Compiling Sass with Webpack (and local scope class names)

I've spent hours attempting to get my Webpack config to compile Sass; it's kinda ridiculous. During my research I found dozens of Github issues, Stackoverflow posts, and blogs talking about how to use Sass with Webpack, and they all do it differently. Also, there are so many people with problems. I just think Webpack needs to be better documented. Ugh.

I figured out how to compile Sass and have Webpack serve it in memory from

/static
, but I want the class names to be locally scoped. Isn't that one of the benefits of modular CSS with React components?

Example of locally scoped:
.foo__container___uZbLx {...}


So, this is my Webpack config file:

const webpack = require('webpack');
const path = require('path');
const ExtractTextPlugin = require('extract-text-webpack-plugin');

module.exports = {
devtool: 'source-map',
entry: {
bundle: './src/js/app'
},
output: {
path: __dirname,
filename: '[name].js',
publicPath: '/static'
},
plugins: [
new webpack.optimize.OccurrenceOrderPlugin(),
new ExtractTextPlugin('[name].css', {allChunks: true})
],
module: {
loaders: [
{
test: /\.js$/,
exclude: /node_modules/,
include: path.join(__dirname, 'src'),
loader: 'babel'
},
{
test: /\.scss$/,
exclude: /node_modules/,
include: path.join(__dirname, 'src'),
loader: ExtractTextPlugin.extract('style', 'css?sourceMap!sass')
}
]
}
};


I managed to get it to work for vanilla CSS:

{
test: /\.css$/,
exclude: /node_modules/,
include: path.join(__dirname, 'src'),
loader: ExtractTextPlugin.extract('style', 'css?modules&importLoaders=1&localIdentName=[name]__[local]___[hash:base64:5]')
}


I don't really understand the parameter-like syntax with all the
?
marks, and I don't know what to search for to find documentation pertaining to that.

This is what my React component looks like; just incase you want to see how I am importing the style:

import React, { Component } from 'react';
import s from './foo.css';

class Foo extends Component {
render() {
return (
<div className={s.container}>
<h1 className="title">Welcome!</h1>
<p className="body">This is a dummy component for demonstration purposes.</p>
</div>
);
}
}

export default Foo;


Also, I have three unrelated questions:


  • What's the point of
    output.path
    property if Webpack merely serves the file from memory by means of
    /static
    ?

  • What's the point of
    webpack-dev-server
    if what I am doing here is adequate? From my understanding,
    webpack-dev-server
    is just for hot module replacement stuff, right? Just automatic refreshing?

  • Are my
    exclude
    and
    include
    properties redundant? From my understanding, excluding
    node_modules
    decreases the compilation time making it work quicker; less files to process.


Answer

I got it to work with this:

loader:  ExtractTextPlugin.extract('style', 'css?modules&localIdentName=[name]__[local]___[hash:base64:5]!sass')

All I had to do was put !sass at the end of the query. I wish this stuff was better documented; can't find adequate docs anywhere...