0

I'm trying to setup a project with react that uses a combination of scss (mixins, variables, etc) and css modules.

However when I setup up webpack using style-loader, css-loader, postcss-loader, sass-loader, sass-resources-loader, import-glob-loader. I get an error that is the following:

Worker error  Error: Unexpected token string «./node_modules/css-   
 loader/index.js?"importLoaders":1,"modules":true,"localIdentName" 
 :"[name]__[local]___[hash:base64:5]"!./node_modules/postcss-loade 
 r/lib/index.js?!./node_modules/sass-loader/lib/loader.js!./node_m 
 odules/sass-resources-loader/lib/loader.js?"resources":["/Users/* 
 ***/Documents/Repos/project/src/scss/*.scss"]!./node_modules/impo 
 rt-glob-loader/index.js!./src/App/App.scss», expected punc «,»    
     at objectToError (/Users/****/Documents/Repos/project/node_mo 
 dules/workerpool/lib/WorkerHandler.js:63:14)                      
     at ChildProcess.<anonymous> (/Users/****/Documents/Repos/ui- 
 kit/node_modules/workerpool/lib/WorkerHandler.js:146:32)          
     at emitTwo (events.js:125:13)                                 
     at ChildProcess.emit (events.js:213:7)                        
     at emit (internal/child_process.js:774:12)                    
     at _combinedTickCallback (internal/process/next_tick.js:141:1 
 1)                                                                
     at process._tickCallback (internal/process/next_tick.js:180:9 
 ) filename: '0', line: 18, col: 936, pos: 2292     

Webpack Scss

const webpack = require('webpack');
const path = require('path');

const DashboardPlugin = require('webpack-dashboard/plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const autoprefixer = require('autoprefixer');

const nodeEnv = process.env.NODE_ENV || 'development';
const isProduction = nodeEnv === 'production';

const jsSrcPath = path.join(__dirname, './');
const publicPath = path.join(__dirname, './public');
const imgPath = path.join(__dirname, './src/assets/img');
const srcPath = path.join(__dirname, './src');

/* Common plugins */

const plugins = [
    new webpack.DefinePlugin({
        'process.env': {
            NODE_ENV: JSON.stringify(nodeEnv)
        }
    }),
    new webpack.NamedModulesPlugin(),
    new HtmlWebpackPlugin({
        template: path.join(publicPath, 'index.html'),
        path: publicPath,
        filename: 'index.html',
    }),
    new webpack.NoEmitOnErrorsPlugin(),
];

/* Common Rules */
const rules = [{
        test: /\.(js|jsx)$/,
        include: path.join(__dirname, 'src'),
        exclude: path.resolve(__dirname, "node_modules"),
        loader: "babel-loader"
    },
    {
        test: /\.scss$/,
        use: [
            'style-loader',
            {
                loader: 'css-loader',
                options: {
                  importLoaders: 1,
                  modules: true,
                  localIdentName: "[name]__[local]___[hash:base64:5]"
                }
            },
            {
                loader: 'postcss-loader',
                options: {
                    plugins: () => [autoprefixer]
                }
            },
            'sass-loader',
            {
                loader: 'sass-resources-loader',
                options: {
                    resources: [
                        path.resolve(__dirname, "./src/scss/*.scss")
                    ]
                }
            },
            'import-glob-loader'
        ]
    },
    {
        test: /\.woff$/,
        loader: "url-loader?limit=10000&mimetype=application/font-woff&name=[path][name].[ext]"
    }, {
        test: /\.woff2$/,
        loader: "url-loader?limit=10000&mimetype=application/font-woff2&name=[path][name].[ext]"
    },
    {
        test: /\.(png|gif|jpg|svg)$/,
        include: imgPath,
        use: 'url-loader?limit=20480&name=assets/[name]-[hash].[ext]',
    }
];

if (isProduction) {
    // Production plugins
    plugins.push(
        new webpack.LoaderOptionsPlugin({
            minimize: true,
            debug: false,
        }),
        new webpack.optimize.UglifyJsPlugin({
            compress: {
                warnings: false,
                screw_ie8: true,
                conditionals: true,
                unused: true,
                comparisons: true,
                sequences: true,
                dead_code: true,
                evaluate: true,
                if_return: true,
                join_vars: true,
            },
            output: {
                comments: false,
            },
        }),
    );

    // Production rules

} else {
    // Development plugins
    plugins.push(
        new webpack.HotModuleReplacementPlugin(),
        new DashboardPlugin()
    );
    // Development rules

}

module.exports = {
    devtool: isProduction ? 'eval' : 'source-map',
    context: jsSrcPath,
    entry: [
        'babel-polyfill',
        './src/index.js'
    ],
    output: {
        path: publicPath,
        publicPath: '/',
        filename: 'app-[hash].js',
    },
    module: {
        rules,
    },
    resolve: {
        extensions: ['.webpack-loader.js', '.web-loader.js', '.loader.js', '.js', '.jsx'],
        modules: [
            path.resolve(__dirname, "node_modules"),
            jsSrcPath
        ]
    },
    plugins,
    devServer: {
        contentBase: isProduction ? './public' : './src',
        historyApiFallback: true,
        port: 3000,
        compress: isProduction,
        inline: !isProduction,
        hot: !isProduction,
        host: '0.0.0.0',
        stats: {
            assets: true,
            children: false,
            chunks: false,
            hash: false,
            modules: false,
            publicPath: false,
            timings: true,
            version: false,
            warnings: true,
            colors: {
                green: '\u001b[32m'
            }
        }
    }
};

react:

import React, { Component } from 'react'
import PropTypes from 'prop-types'
import { bindActionCreators } from 'redux'
import { connect } from 'react-redux'

import styles from './App.scss';

class App extends Component {
  render() {
    return (
      <div>
        <h1 className={styles.main}>Hello World</h1>
      </div>
    )
  }
}

const mapStateToProps = (state) => {
    return {
        app: state.app
    };
};

export default connect(mapStateToProps, null)(App)

App.scss file

.main { color: red; }

Anyone else have this issue before?

3 Answers 3

1

It appears your exclude: path.resolve(__dirname, "node_modules"), to be blamed. Can you try after removing that from the loaders ?

To give you more insight: the error is reporting something about node_modules/css-loader/index.js. A java script file. In your js|jsx rule (i.e. babel-loader) you are excluding node_modules entirely. That is the problem cause.

UPDATE : issue cause code

Sign up to request clarification or add additional context in comments.

2 Comments

I'm not using exclude : [/\.global\./, /node_modules/]. I have tried to exclude node_modules in scss part of webpack config. Still get the same error
@themaster Yikes! My bad. Updated the answer to reflect the problematic exclude and further details.
0

Full for reference

  module: {
    rules: [
        {
            test: /\.js$/,
            exclude: /node_modules/,
            loader: 'babel-loader',
        },

        {
            test: /\.scss$/,
            loader: ExtractPlugin.extract(['css-loader', 'sass-loader']),
        },
        {
            test: /\.css$/,
            exclude: [/\.global\./, /node_modules/],
            loader: ExtractPlugin.extract(
                {
                    fallback: 'style-loader',
                    use: [
                        {
                            loader: 'css-loader',
                            options: {
                                importLoaders: 1,
                                modules: true,
                                autoprefixer: true,
                                minimize: true,
                                localIdentName: '[name]__[local]___[hash:base64:5]'
                            }
                        }
                    ]
                })
        },

Comments

0

Still not 100% sure why this works but I added extract-text-plugin and it fixed my issues.

{
        test: /\.s?css$/,
        use: ExtractTextPlugin.extract({
            fallback: 'style-loader',
            use: [
                {
                    loader: 'css-loader',
                    options: {
                        modules: true,
                        importLoaders: 1,
                        localIdentName: '[name]__[local]___[hash:base64:5]'
                    }
                },
                {
                  loader: 'postcss-loader',
                  options: {
                    plugins: () => [autoprefixer]
                  }
                },
                'sass-loader'
            ]
        })
    }

also add new ExtractTextPlugin({ filename: '[name].css' }), to plugins

1 Comment

Glad you found a way. In case if any questions, do check my updated answer. Hope it helps.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.