0
votes

How correctly to add sass(in jsx import 'style.sass') in a config webpack + react?

var path = require('path');

var BUILD_DIR = path.resolve(__dirname, './');
var APP_DIR = path.resolve(__dirname, 'src/');

var config = {
    entry: APP_DIR + '/index.jsx',
    output: {
        path: BUILD_DIR,
        filename: 'bundle.js'
    },
    devServer: {
        contentBase: BUILD_DIR
    },
    module: {
        loaders: [
            {
                test: /\.jsx?/,
                include: APP_DIR,
                loader: 'babel-loader'
            }
        ]
        ,
        rules: [{
            test: /\.scss$/,
            use: [{
                loader: "style-loader" // creates style nodes from JS strings
            }, {
                loader: "css-loader" // translates CSS into CommonJS
            }, {
                loader: "sass-loader" // compiles Sass to CSS
            }]
        }]
    }
};

module.exports = config;

Error:

ERROR in ./src/index.jsx Module parse failed: C:\Users\steko\Desktop\TEST\m-react\src\index.jsx Unexpected token (9:8) You may need an appropriate loader to handle this file type. | render () { | return ( | | Hello React Project!!! |

git

3

3 Answers

2
votes

In your modules section in webpack do this

module: {
    rules: [
        {
            test: /\.jsx?/,
            loader: 'babel-loader',
            include: APP_DIR
        },
        {
            test: /\.scss$/,
            use: ExtractTextPlugin.extract({
                fallback: "style-loader",
                use: "css-loader!sass-loader",
            })
        }
    ]
}

Then in your plugins area in your webpack code do this

plugins: [
    new ExtractTextPlugin('style.css'),
]

You will need this package extract-text-webpack-plugin

Please do let me know if you still have any issues.

1
votes

The ExtractTextPlugin above me, is for extracting your js code and css code to 2 separate files. This is great, but not sure that is what you meant.

So this is how I parse sass files in my webpack build. I can later decide if I leave the css in my js file or extract it.

 loaders: [
        {
            test: /\.scss$/,
            loader: "style-loader!css-loader!sass-loader"
        }
 ]

the loaders are applied right to left so:

  • parsing the sass file
  • then applying the css loader
  • and finally the style loader

in the end you will have your css code inside your js output file ready for use, just like any other css file you load.

0
votes

This might make it more confusing, but I thought to send you a copy of the file that I use for the dev environment which includes SASS and React. you should be able to decifer what is needed and not needed.

I have excluded anything that is directly work related such as IP address used for a proxy in the devServer setup but other than that it is complete.

hope it helps!

const webpack           = require('webpack');
const path              = require('path');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const CopyWebpackPlugin = require('copy-webpack-plugin');

const Paths = {
    dist:           path.resolve(__dirname, 'dist'),
    src:            path.resolve(__dirname, 'src'),
    indexFile:      path.resolve(__dirname, 'src/index.jsx'),
    nodeModulesDir: path.resolve(__dirname, 'node_modules'),
    sassFile:       path.resolve(__dirname, 'assets/css/main.scss')
};

const config = {
    devtool: '#source-map',
    entry: {
        main: ['react-hot-loader/patch', 'babel-polyfill', Paths.indexFile, Paths.sassFile],
    },
    output: {
        path: Paths.dist,
        filename: "[name].[hash].bundle.js",
        publicPath: "/"
    },
    module: {
        rules: [
            {
                test: /\.(js|jsx)$/,
                exclude:  [Paths.nodeModulesDir],
                use:   [{
                    loader: 'babel-loader?cacheDirectory&cacheIdentifier='+ Math.random(),
                    options: {
                        presets: ["env", "react", "stage-0",
                            ["env", {
                                "targets": {
                                    "browsers": ["last 2 versions", "ie >= 8", "safari >= 7"]
                                },
                                debug: true
                            }]
                        ]
                    }
                }]
            },
            {
                test: /\.css/,
                use: ExtractTextPlugin.extract({
                    fallback: 'style-loader',
                    use: [
                        {
                            loader: 'css-loader',
                            options: {
                                modules: true,
                                localIdentName: '[name]_[local]__[hash:base64:5]'
                            }
                        },
                        'postcss-loader'
                    ]
                })
            },
            {
                test: /\.scss$/,
                use: ExtractTextPlugin.extract({
                    fallback: 'style-loader',
                    use: [
                        {
                            loader: 'css-loader',
                            options: {
                                modules: false,
                                sourceMap: true,
                                importLoaders: 2,
                                localIdentName: '[name]_[local]__[hash:base64:5]'
                            }
                        },
                        'sass-loader'
                    ]
                })
            },
            {
                test: /\.(eot|woff|woff2|ttf|svg|png|jpe?g|gif)(\?\S*)?$/,
                use: [
                    {
                        loader:  'url-loader',
                        options: {
                            limit: 100000,
                            name: '[name].[ext]'
                        }
                    }
                ]
            }
        ]
    },
    resolve: {
        extensions: ['.js', '.jsx'],
        modules: ['node_modules', 'src']
    },
    plugins: [
        new webpack.DefinePlugin({
            'process.env.NODE_ENV': JSON.stringify('development')
        }),
        new HtmlWebpackPlugin({
            template: path.join(Paths.src, 'index.html')
        }),
        new ExtractTextPlugin({filename: "[name].[contenthash].css", allChunks: true}),
        new CopyWebpackPlugin([
            {from: 'assets/images/**/*', to: ''},
            {from: 'assets/fonts/**/*', to: ''},
            {from: 'assets/lang/**/*', to: ''},
            {from: 'assets/js/**/*', to: ''},
            {from: 'src/static/**/*', to: ''}
            ]),
        new webpack.HotModuleReplacementPlugin(),
        new webpack.NamedModulesPlugin()
    ],
    devServer: {
        port: 8081,
        host: '127.0.0.1',
        disableHostCheck: true, // so you can use the computers IP address not just 'localhost'/127.0.0.1
        contentBase: Paths.src,
        historyApiFallback: true,
        hot: true,
        headers: {
            "Access-Control-Allow-Origin": "http://localhost:8081",
            "Access-Control-Allow-Methods": "GET, POST, PUT, DELETE, PATCH, OPTIONS",
            "Access-Control-Allow-Headers": "X-Requested-With, content-type, Authorization"
        },
        inline: true
        }
    }
};