11

I am trying to implement CSS modules to my project which is using React and Webpack. But, I want to keep using all the global css that I have created.

For example, previously I imported css in React like this

import './styles.scss'

And then, there will be a html element using the class .button which exists inside ./styles.scss

<button className='button'>Click me</button>

Now since I want to implement CSS modules, I modified the css-loader config in webpack like this

module: {
  rules: [{
    test: /\.s?css$/,
    use: [
      'style-loader',
      {
        loader: 'css-loader',
        options: {
          // This is where I added the config for css modules
          modules: true,
          localIdentName: '[hash:base32:5]-[name]-[local]',
          importLoaders: 2,
        }
      },
      {
        loader: 'postcss-loader',
        options: {
          config: {
            path: './postcss.config.js',
          },
        },
      },
      'sass-loader',
    ]
  }]
}

However, now I cannot use the button classname when I import like this

import './styles.scss'

Because the classnames in ./styles.scss are all converted to hash-based classnames like 32osj-home-button

Basically, how do I configure the css-loader to load css normally when I import this way

import './styles.scss'

But use css modules when I import this way?

import styles from './styles.scss'

OR

Is there any configuration available to set css modules to load all css in :global by default, and only load css in :local when I specify it?

FYI, I know I can make 2 loader configs to apply css modules for css file named this way

styles.modules.scss

and apply normal css-loader for default named css

styles.scss

But, I prefer not to do so since it will create more files after Webpack bundles them.

2 Answers 2

8

With css modules I use it this way:

import styles from './styles.scss'

<button className={styles.button}>Click me</button>

The imported styles is actual a map with [className] => [hashed_className]

Everything you put in a :global block is not converted to css hashed names

:global {
    .button {
        color: #FF0000;
    }
}
.button {
    color: #000000;
}

should output

.button {
    color: #FF0000;
}
.32osj-home-button {
    color: #000000;
}
Sign up to request clarification or add additional context in comments.

Comments

3

This is my setup... I can do what you want to do.

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]'
                            }
                        }
                    ]
                })
        },
        {
            test: /\.css/,
            include: [/\.global\./, /node_modules/],
            loader: ExtractPlugin.extract(
                {
                    fallback: 'style-loader',
                    use: ['css-loader']
                })
        },
        {
            test: /\.(woff|woff2|ttf|eot|glyph|\.svg)$/,
            use: [
                {
                    loader: 'url-loader',
                    options: {
                        limit: 10000,
                        name: 'font/[name].[ext]',
                    },
                },
            ],
        },
        {
            test: /\.(jpg|jpeg|gif|png|tiff|svg)$/,
            exclude: /\.glyph.svg/,
            use: [
                {
                    loader: 'url-loader',
                    options: {
                        limit: 6000,
                        name: 'image/[name].[ext]',
                    },
                },
            ],
        },
        {
            test: /\.(mp3|aac|aiff|wav|flac|m4a|mp4|ogg)$/,
            exclude: /\.glyph.svg/,
            use: [
                {
                    loader: 'file-loader',
                    options: { name: 'audio/[name].[ext]' },
                },
            ],
        },

1 Comment

Thank you for your answer, but I think this is not exactly what I'm looking for. CMIIW, but basically you exclude files which contains .global. to be parsed as css modules. I already have lots of css files and I want to keep the names and location of those files the same. If I do it your way, I either need to change their file name or move them to a .global. folder, which I don't want to do.

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.