Skip to content

Conversation

@alexandreIFB
Copy link
Contributor

Summary

Fix CSS class name generation for .module.less files in production builds: the literal [local] placeholder was not expanded, producing names like Component-module__[local]___Abc12. It is now correctly replaced, yielding Component-module__container___Abc12.

Context / Problem

In production (dev=false), the webpack-less-plugin provides a custom getLocalIdent. When getLocalIdent is defined, css-loader skips its usual post-processing of localIdentName. Our implementation called interpolateName directly, which doesn’t know the [local] token, leaving it untouched.

Observed:

Carousel-module__[local]___KTvpt

Expected:

Carousel-module__slide___KTvpt

It went unnoticed because in development mode (dev=true) the custom getLocalIdent isn't applied.

Reproduction Steps

  1. Create Example.module.less:
    .container {
      color: red;
    }
  2. Import in a React component:
    import styles from './Example.module.less';
    <div className={styles.container}>Test</div>
  3. Run a production build:
    pnpm --filter @plone/volto build
    
  4. Inspect generated CSS and find a class with literal [local].
  5. In dev mode (pnpm --filter @plone/volto start) the name is correct.

Implemented Solution

In webpack-less-plugin.js, inside getLocalIdent:

  • Manually replace all [local] occurrences with localName before calling interpolateName.

Risks / Impact

  • Production class names for .module.less change (now correct). Any global overrides relying on the buggy literal [local] will stop working (expected).
  • Hash stability preserved (hash content basis unchanged).

Closes #7587

@wesleybl
Copy link
Member

wesleybl commented Nov 4, 2025

I can confirm this problem.

I can also confirm that updating to the latest version of css-loader (7.1.2) and removing the customization in getLocalIdent resolves the issue.

However, version 7 brings significant changes that break compatibility:

  • import styles from './Example.module.less'; does not work. It has to be: import * as styles from './Example.module.less';

  • Using base64 in the value of a CSS property does not work:

border-image: url('data:image/svg+xml;base64,abc...');

But there is a workaround, see: webpack/css-loader#1367

Perhaps this fix can help for Volto18. But we need to check if we can update the css-loader version in Volto 19.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Production LESS CSS Modules emit literal [local] in class names

2 participants