I have configured webpack to use ExtractTextPlugin for generating a single css file from sass as well as allowing it to be available within a reactjs app via import through a webpack loader.
The usage of the sass files are detected through the import statement in the react component and an output file is being generated however the main.css file that is generated is empty and the import is returning an empty style object, does anyone know what I am doing incorrectly?
Structure
client
- app
- components
- navbar
Navbar.js
navbar.scss
- public
- styles
main.scss
bundle.js
index.html
Webpack Config
const webpack = require('webpack');
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const BUILD_DIR = path.resolve(__dirname, 'public');
const APP_DIR = path.resolve(__dirname, 'app');
const config = {
entry: APP_DIR + '/index.js',
output: {
path: BUILD_DIR,
filename: 'bundle.js'
},
externals: {
'cheerio': 'window',
'react/lib/ExecutionEnvironment': true,
'react/lib/ReactContext': true,
},
module : {
loaders : [
{
test : /\.jsx?/,
include : APP_DIR,
loader : 'babel'
},
{
test: /\.scss$/,
include : APP_DIR,
loader: ExtractTextPlugin.extract('css!sass')
}
]
},
plugins: [
new HtmlWebpackPlugin({
title: 'My App'
}),
new ExtractTextPlugin('styles/main.css', {
allChunks: true
})
]
};
module.exports = config;
navbar.scss
.navbar {
display: flex;
.navbarBrand {
}
}
Navbar.js
import React, { Component, PropTypes } from 'react'
import classnames from 'classnames'
import Login from '../login/Login'
import Logout from '../logout/Logout'
import styles from './navbar.scss';
export default class Navbar extends Component {
render() {
const { isAuthenticated, errors, onLogin, onLogout } = this.props;
console.log(styles);
const navBarStyles = classnames(styles.navbar);
const navBarBrandStyles = classnames(styles.navbarBrand);
return (
<nav className={navBarStyles}>
<div className='container-fluid'>
<a className={navBarBrandStyles} href="#">User Management App</a>
<div className='navbar-form'>
{!isAuthenticated &&
<Login
errors={errors}
onLoginClick={ (creds) => onLogin(creds) }
/>
}
{isAuthenticated &&
<Logout onLogoutClick={() => onLogout()} />
}
</div>
</div>
</nav>
)
}
}
Navbar.propTypes = {
isAuthenticated: PropTypes.bool.isRequired,
errors: PropTypes.arrayOf(PropTypes.string),
onLogin: PropTypes.func.isRequired,
onLogout: PropTypes.func.isRequired
};
Symptoms
Loaders and Imports (NO longer an issue, please refer to answer below)
console.log(styles) = Object {}
styles.navbar = undefined
Plugins
Questions
sass-loader fixed.
The key is the add modules=true for the css-loader, you can then import you for styles from the scss files.
{
test: /\.scss$/,
loader: extractCSS.extract('style', 'css?modules=true!sass?sourceMap=true')
}
public/style/main.css fixed.
To be honest I am not sure what the difference is but the public/styles/main.css file is now populated.
The only change I made is to the webpack config.
const webpack = require('webpack');
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const BUILD_DIR = path.resolve(__dirname, 'public');
const APP_DIR = path.resolve(__dirname, 'app');
let generateHtml = new HtmlWebpackPlugin({ title: 'My App' });
let extractCSS = new ExtractTextPlugin('styles/[name].css', { allChunks: true });
const config = {
entry: APP_DIR + '/index.js',
output: {
path: BUILD_DIR,
filename: 'bundle.js'
},
externals: {
'cheerio': 'window',
'react/lib/ExecutionEnvironment': true,
'react/lib/ReactContext': true,
},
module : {
loaders : [
{
test : /\.jsx?/,
include : APP_DIR,
loader : 'babel'
},
{
test: /\.scss$/,
loader: extractCSS.extract('style', 'css?modules=true!sass?sourceMap=true')
}
]
},
plugins: [
generateHtml,
extractCSS
]
};
module.exports = config;