6

I want to use the .scss in my project(bulid with react and typescript),so I use typings-for-css-modules-loader with css-loader and sass-loader.

When I npm run dev, I get this error:

./src/Common.scss
Module build failed (from ./node_modules/mini-css-extract-plugin/dist/loader.js):
ModuleBuildError: Module build failed (from ./node_modules/sass-loader/lib/loader.js):

.common {
^
      Invalid CSS after "e": expected 1 selector or at-rule, was "exports = module.ex"

my.scss like this:

.common {
  height: 100px
}

and my wepack.config is:

module.exports = {
    mode: 'development',
    entry: [
        'webpack-dev-server/client',
        path.resolve(root, 'src/index.tsx')
    ],
    devtool: 'inline-source-map',
    devServer: {
        contentBase: './dist',
        publicPath: '/',
        port: 8080,
        historyApiFallback: true
    },
    resolve: {
        extensions: [".ts", ".tsx", ".scss", ".js", ".json", "css"]
    },
    plugins: [
        new CleanWebpackPlugin(['dist']),
        new BundleAnalyzerPlugin(),
        new MiniCssExtractPlugin({
            filename: devMode ? '[name].css' : '[name].[hash].css',
            chunkFilename: devMode ? '[id].css' : '[id].[hash].css',
        })
    ],
    output: {
        filename: 'bundle.js',
        path: path.resolve(root, 'dist'),
        publicPath: '/'
    },
    module: {
        rules: [
            {
                test: /\.tsx?$/,
                use: 'ts-loader'
            },
            {
                test: /\.(js|jsx)$/,
                use: 'babel-loader',
                exclude: /node_modules/
            },
            {
                test: /\.(sa|sc|c)ss$/,
                use: [{
                    loader: devMode ? MiniCssExtractPlugin.loader : 'style-loader'
                }, {
                    loader: 'css-loader',
                    options: {
                        sourceMap: true,
                        modules: true,
                    }
                }, {
                    loader: 'sass-loader', options: {
                        sourceMap: true
                    }
                }]
            },
            { test: /\.(c|sc)ss$/, loader: 'typings-for-css-modules-loader?modules&sass' },
            {
                test: /\.(jpg|png|gif)$/,
                use: [{
                    loader: 'file-loader',
                    options: {
                        name (file) {
                            if (devMode === 'development') {
                              return '[path][name].[ext]'
                            }

                            return '[hash].[ext]'
                        }
                    }
                }]
            }
        ]
    },
    optimization: {
        splitChunks: {
            chunks: 'all'
        }
    }
};

When I use css-loader with sass-loader or single use typings-for-css-modules-loader, this error is fix.

But I get another error like this:

ERROR in /Users/hly/Bpeanut.github.io/src/app/HeaderBar.tsx
./src/app/HeaderBar.tsx
[tsl] ERROR in /Users/hly/Bpeanut.github.io/src/app/HeaderBar.tsx(40,39)
      TS2339: Property 'header' does not exist on type 'typeof import("/Users/hly/Bpeanut.github.io/src/app/HeaderBar.scss")'.

HeaderBar.tsx like this(the error is here):

import * as styles from './HeaderBar.scss';

class default HeaderBar extends Component {
    render() {
        return(<div className={styles.header}>123</div>)
                                        ^
    }
}

and HeaderBar.scss like:

.header {
    height: 100px;
}

HeaderBar.scss.d.ts:

export interface IHeaderBarScss {
  'header': string;
}

export const locals: IHeaderBarScss;

Now I find another way to fix it.

Use const styles = require('./HeaderBar.scss'); instead of import * as styles from './HeaderBar.scss';

and it work.

thanks.

1
  • according to the docs you have to replace css-loader with typings-for-css-modules-loader. Currently you use both which probably causes the error. Commented May 14, 2019 at 15:11

3 Answers 3

2

I don't use typings-for-css-modules-loader for my projects with css and scss and with this configuration it works very well :

{
    test: /\.s?css$/,
    use: [
        {
            loader: MiniCssExtractPlugin.loader,
            options: {
                sourceMap: true
            }
        },
        {
        loader: 'css-loader',
            options: {
                sourceMap: true
            }
        },
        {
            loader: 'sass-loader',
            options: {
                sourceMap: true
            }
        }
    ]
},

Does that fix your error?

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

4 Comments

thanks. I used the same with you in the past. It can fix this error. But there is another one exposed.
@LoveY.H What is the new one ?
I wrote it under the webpack.config. It's my fault. thanks.
@LoveY.H All right :) In this case please validate my answer
1

Chain the sass-loader with the css-loader and the style-loader to immediately apply all styles to the DOM.

npm install style-loader css-loader sass-loader --save-dev

// webpack.config.js

module.exports = {
    ...
    module: {
        rules: [{
            test: /\.scss$/,
            use: [
                "style-loader", // creates style nodes from JS strings
                "css-loader", // translates CSS into CommonJS
                "sass-loader" // compiles Sass to CSS, using Node Sass by default
            ]
        }]
    }
};

For further information please visit sass loader

Comments

1

I stumbled upon this question when looking for a way to use CSS modules in my create-react-app project. Therefore, adding the answer for the create-react-app scenario.

The SCSS or CSS module file name should end with module.scss or module.css in order to be able to use in create-react-app projects.

The following example shows a component QuestionForm.tsx and a SCSS module QuestionForm.module.scss working together.

// QuestionForm.tsx

import React, { useState } from 'react';
import style from './QuestionForm.module.scss';

export type PersonalData = {
  name: string;
};

type QuestionFormProps = {
  personalData: PersonalData;
  onChange: (data: PersonalData) => void;
};

export const QuestionForm: React.FC<QuestionFormProps> = ({ personalData, onChange }) => {
  const [name, setName] = useState<string>(personalData.name);

  const handleSubmit = (event: React.FormEvent) => {
    event.preventDefault();
    onChange({ name });
  };

  const handleNameChange = (event: React.ChangeEvent<HTMLInputElement>) => {
    setName(event.target.value);
  };

  return (
    <form className={style.container} onSubmit={handleSubmit}>
      <div className={style.titleWrapper}>
        <h2 className={style.title}>Questionnaire</h2>
      </div>
      <label>
        What is your name?
        <input type="text" minLength={2} maxLength={20} value={name} onChange={handleNameChange} required />
      </label>
      <div className={style.cta}>
        <input className="buttonPrimary" type="submit" value="Submit" />
      </div>
    </form>
  );
};
// QuestionForm.module.scss

@mixin flex($direction: row, $align: center, $justify: center) {
  align-items: $align;
  display: flex;
  flex-direction: $direction;
  justify-content: $justify;
  width: 100%;
}

.container {
  @include flex(column, flex-end, space-evenly);

  border: 1px solid whitesmoke;
  border-radius: 5px;
  height: 230px;
  padding: 0 10px;
  width: 400px;
}

.cta {
  @include flex();
}

.titleWrapper {
  @include flex();
}

.title {
  font-size: 1.5rem;
  font-weight: bold;
}

Comments

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.