madyankin / postcss-modules

PostCSS plugin to use CSS Modules everywhere
MIT License
1.59k stars 86 forks source link

How to use postcss-modules in combination with css-loader modules? #117

Open samuelg0rd0n opened 3 years ago

samuelg0rd0n commented 3 years ago

I use postcss-modules to generate JSON mapping file that I'm using on the server (in PHP). But I also wanted to use CSS modules directly in my JS files like this:

import styles from './index.module.scss';
console.log(styles);

What I get from the JSON file, must be the same as styles. So let's say it should be for example (simplified):

{
    input: "app-Components-Forms-ExampleForm-input__12BrH"
}

My webpack.config.js currently looks something like this (simplified):

...
{
    test: /\.module.scss$/,
    use: [{
        loader: MiniCssExtractPlugin.loader,
    }, {
        loader: 'css-loader',
        options: {
            modules: {
                localIdentName: '[path][local]__[hash:base64:5]',
            },
        }
    }, {
        loader: 'postcss-loader',
        options: {
            plugins: function () {
                return [
                    PostCssModules({
                        generateScopedName: '[path][local]__[hash:base64:5]',
                    }),
                ];
            }
        }
    }, {
        loader: 'sass-loader',
    }]
},
...

I came across several problems and I feel like I'm running in circles:

1) If I leave it exactly like above, JSON file is correct but postcss-modules actually changes local name used in css-loader so styles looks something like this:

    {
        app-Components-Forms-ExampleForm-input__12BrH: "app-Components-Forms-ExampleForm-app-Components-Forms-ExampleForm-input__12BrH__U4gah"
    }

2) If I don't include modules option in css-loader, JSON file is correct but styles is an empty object.

3) If I omit postcss-modules, styles looks as desired but of course, no JSON file is generated, and I need this for server part.

Why does postcss-modules change local variable used in css-loader? Why is styles an empty object if I don't add modules options to css-loader? How can I combine both together?

no95typem commented 3 years ago

@samuelg0rd0n, I faced the same problem. This repo looks a bit abandoned. At the same time, maintainers of the css-loader do not consider it significant to implement the export of generated module names to JSON. So, for now, I decided to do this - generate modules using the postcss-loader, and then generate the modules in the css-loader with: localIdentName parameter: '[local]' As a result I have modules, classes can be written in html using css-module = "" and the styles object is not empty. The only problem is that IDE does not suggest names, but with the help of a small function that selects using regexp, I can find in this object a hashed name by class name in css / scss if I use: generateScopedName: '[local] _ [hash: base64: 5 ] in postсss-module. The initial class name is stored hashed in this case. This is necessary for a possibility to find the new class name in js. But, the main, as I think, hashing function of modules is working in this case - no problems with name conflicts.