reactjswebpackreact-css-modulesbabel-plugin-react-css-modules

babel-plugin-react-css-modules is not matching styles with styleName


Issue

I am trying to use babel-plugin-react-css-modules in my React project for better performance as opposed to React CSS Modules.

However, the styles are being not applied correctly.

Cause

The version in <style> tag is wrapped with weird hypen, for example:

Even if we are using the same localIdentName, the generated results are different from selectors in css and className on DOM element.

(Note: In babel-plugin-react-css-modules, the localIdentName is [path]___[name]__[local]___[hash:base64:5] as hard-coded in options.generateScopedName)

Any idea why there is a hypen-wrapper?


Solution

  • Found the solution myself after some struggling.

    Cause

    This is due to a quirk of css-loader: if there are double quotes around localIdentName option, it will wrap the generated class name with hyphens.

    Working Examples

    So instead of doing this in webpack config:

    {
        test: /\.(scss|sass)$/,
        use: [
            'style-loader?sourceMap',
            'css-loader?modules="true"&importLoaders="1"&localIdentName="[path]___[name]__[local]___[hash:base64:5]"',
            'sass-loader?sourceMap',
        ],
    },
    

    Do this:

    {
        test: /\.(scss|sass)$/,
        use: [
            'style-loader?sourceMap',
            'css-loader?modules="true"&importLoaders="1"&localIdentName=[path]___[name]__[local]___[hash:base64:5]',
            'sass-loader?sourceMap',
        ],
    },
    

    Or event better if you are using Webpack 2+

    {
            test: /\.(scss|sass$/,
            use: [
              'style-loader',
              {
                loader: 'css-loader',
                options: {
                  importLoaders: 1,    
                  modules: true,
                  sourceMap: true,
                  localIdentName: '[path]___[name]__[local]___[hash:base64:5]'
                }
              },
              'sass-loader'
            ]
    }