gajus / babel-plugin-react-css-modules

Transforms styleName to className using compile time CSS module resolution.
Other
2.05k stars 162 forks source link

Temporary fix for those have trouble with newer version of webpack / css-loader. #304

Open PieNam opened 2 years ago

PieNam commented 2 years ago

It turns out that babel-plugin-react-css-modules is using generic-names v2, which is different a bit with newer Webpack in the [hash].

generic-names v3 solve it. see this update.

So we can manually replace the generateScopedName with createGenerator from generic-names v3.

Like this

const createGenerator = require('generic-names');

const plugins = [
  [
    'babel-plugin-react-css-modules',
    {
      generateScopedName: createGenerator('[name]__[local]_[hash:base64:5]'),
      exclude: 'node_modules',
    },
  ],
];

I've done this in my own project and it works fine. Have a try. Best wishes~

PieNam commented 2 years ago

But still, the best way to solve this is an update of this package. LOL 😂

wallzero commented 2 years ago

I just gave this a try and the hash in the JSX still failed to match the hash in the generated CSS. I tried with latest generic-names and css-loader. Mind you I am using a custom localIdentName which matches my generateScopedName: [local]-[hash:6].

PieNam commented 2 years ago

I just gave this a try and the hash in the JSX still failed to match the hash in the generated CSS. I tried with latest generic-names and css-loader. Mind you I am using a custom localIdentName which matches my generateScopedName: [local]-[hash:6].

Sorry to hear that. Have you checkout the name-generator of css in your builder like webpack to see if its using the newest generic-names?

PieNam commented 2 years ago

I've found out an approach that is more decent with yarn. If you're using yarn as your package manager, try resolutions property in the package.json like:

{
  "resolutions": {
    "generic-names": "^3.0.0"
  },
}

This force all packages in node_modules to use generic-names in version 3, which ensure that the babel-plugin are using the same name generator with the builder (css generator).

wallzero commented 2 years ago

I am not using yarn but instead I tried npm-force-resolutions and confirmed generic-names@^3 with npm list generic-names. Even forcing the latest version on all packages and ensuring the same generateScopedName is used, the hashes still don't match. Furthermore, I am using a shared Webpack configuration and resolutions would need to be added to every downstream project.

For now I am just sticking with css-loader@^3.6.0.

hinok commented 2 years ago

@wallzero I had to also specify context for generic-names like

createGenerator('[local]-[hash:base64:5]', { context: 'src/client' }),
//                                               ^
//                                               |
//                                               |
//                                               |
//                   Without { context } it didn't work correctly

So now my babel.config.js looks +/- like below

const createGenerator = require('generic-names');

// ... later in the code where plugins are defined

[
    'react-css-modules',
    {
      context: 'src/client',
      filetypes: {
        '.scss': {
          syntax: 'postcss-scss',
          plugins: [
            [
              'postcss-nested',
              {
                bubble: ['@include'],
                preserveEmpty: true,
              },
            ],
          ],
        },
      },
      generateScopedName: createGenerator('[local]-[hash:base64:5]', { context: 'src/client' }),
      webpackHotModuleReloading: env === 'development',
      exclude: 'node_modules',
      handleMissingStyleName: 'throw',
    },
  ]

Hopefully it will help somebody. The context options is also mentioned in https://github.com/gajus/babel-plugin-react-css-modules/issues/279#issuecomment-656549514

wallzero commented 2 years ago

@hinok Thanks! I hadn't mentioned I had used the context parameter and I still couldn't get it to work. Although maybe it will help someone else. Like I said, I am using a shared configuration between projects and requiring downstream projects to resolve generic-names isn't an option. Perhaps the shared configuration may also be why setting context was not working?

For now I am using the fork @dr.pogodin/babel-plugin-react-css-modules and it is working well.