Css-loader: babel-plugin-css-modules-transform and css-loader create different class names

Created on 22 Dec 2018  路  10Comments  路  Source: webpack-contrib/css-loader

In ssr module:

require('@babel/register')({
    babelrc: false,
    presets: ['@babel/env', '@babel/react'],
    ignore: [/node_modules/],
    plugins: [
        // '@babel/plugin-proposal-object-rest-spread',
        // '@babel/plugin-proposal-export-default-from',
        // '@babel/plugin-proposal-class-properties',
        [
            'css-modules-transform',
            {
                devMode: true,
                generateScopedName: '[hash:base64]-[local]',
                rootDir: 'f:/'
                // context: process.cwd()
                // extensions: [".css"]
            }
        ]
        // 'css-modules-transform'
    ]
});
require('@babel/polyfill');
require('./src/server');

in webpack config:

rules: [
            {
                test: /\.(sa|sc|c)ss$/,
                use: [
                    MiniCssExtractPlugin.loader,
                    {
                        loader: 'css-loader',
                        options: {
                            modules: true,
                            context: 'f:/',
                            localIdentName: '[hash:base64]-[local]'
                        }
                    },
                    'sass-loader',
                ],
            },
...

output from ssr class name:
_3P6Q-BetHcqJ-0bqToVM2U-intro
output from webpack class name:
DNgallyUyucYR3J-Bkjsb-intro

How to fix it?

Needs more info

Most helpful comment

use css-loader older version, will work

All 10 comments

Can you create minimum reproduceble test repo?

Sure, later. Im post link to repo when finished.

/cc @GlebFeklistov friendly ping

Hi, I encountered the same problem in my Windows environment and i am using css-loader v2.1.0.

Althought i am not 100% sure the cause of my problem is same as the author, i think i may have found out a line of code of css-loader which caused the inconsistent bahavior between the two libs.

Here is the code,
https://github.com/webpack-contrib/css-loader/blob/master/src/utils.js#L45
it replaces the path separator to '/', but i didn't find the same behavior in the flow of babel-plugin-css-modules-transform -> css-modules-require-hook -> generic-names.

Here is the generic-names code,

var loaderOptions = {
  content: util.format('%s%s+%s',
    hashPrefix,
    path.relative(context, filepath),
    localName),
  context: context
};

var genericName = interpolateName(loaderContext, name, loaderOptions);

I don't think the content it uses will contain '/' instead of '\' in the Windows environment. In my debugging process, the content is something like src\shared\styles\XXX.scss+className. Of course, the css-loader will use something like
src/shared/styles/XXX.scss+className.
So i just try to remove the replacement code of css-loader in my local, the warnings disappears.
And i also try to downgrade the css-loader to v1.0.0, there is no warnings too.

I think in my case the workaround is to use the css-loader 1.0.0.

@Feniast it is not workaround, in near future we release webpack@5 and css-loader@1 doesn't work, you need fix it in babel-plugin-css-modules-transform. Why change \ on / for consistently generating classes, without this fix you get difference classes on windows and linux and it is bug.

@evilebottnawi Sorry, i know it's a bug. I found css-modules-require-hook use the old version of generic-names 1.0.1. So it should update its dependency version. But it is not my duty, i never use css-loader and babel-plugin-css-modules-transform together before today and never know what they do and what they use before today. I just want to make it work and go here to report why it didn't work as expected.

I close issue due problem in old dependencies in deps, we can't do here on our side, as workaround you can use own getLocalIdent function https://github.com/webpack-contrib/css-loader#localidentname and https://github.com/webpack-contrib/css-loader/blob/master/src/index.js#L84 to generate classes

Thanks!

use css-loader older version, will work

@GlebFeklistov

in near future we release webpack@5 and css-loader@1 doesn't work, you need fix it in babel-plugin-css-modules-transform

for who would like to keep using the latest version of css-loader, just use postcss-modules to modulize the css file instead.
https://github.com/css-modules/postcss-modules#generating-scoped-names

Example:

// webpack config

      {
        test: /\.css$/,
        include: sompath,
        exclude: sompath,
        enforce: 'pre',
        enforce: 'post',
        use: [
          MiniCssExtractPlugin.loader,
          {
            loader: 'css-loader',
          },
          {
            loader: 'postcss-loader',
            options: {
              plugins: loader => [
                require('postcss-import')({
                  root: loader.resourcePath,
                }),
                require('postcss-modules')({
                  generateScopedName: '[name]__[local]___[hash:base64:5]',
                }),
                require('postcss-cssnext')(),
                require('autoprefixer')(),
                require('cssnano')({ safe: true }),
              ],
            },
          },
        ],
      },
// index.js

import './my.css';
import CSS_MODULE from './my.css.json';  (json file is automatically generate by postcss-modules)
...
<div className={CSS_MODULE.someClassName}/>
...
// .babelrc

{
  "presets": ["@babel/preset-env", "@babel/preset-react"],
  "env":
  {
    "development":
    {

    },
    "production":
    {

    },
    "lib":
    {
      "plugins": [
        ["css-modules-transform",
        {
          "generateScopedName": "[name]__[local]___[hash:base64:5]"
        }],
        "@babel/proposal-class-properties",
        "@babel/proposal-object-rest-spread"
      ],
    },
  }
}
Was this page helpful?
0 / 5 - 0 ratings