CSS Modules类名冲突源于localIdentName未显式配置,导致哈希仅基于类名和文件名生成,忽略路径层级;必须设为path__[local]__[hash:base64:5]并校验大小写与嵌套层级。

CSS Modules 类名冲突不是偶发问题,而是配置缺失或不匹配的必然结果——只要 localIdentName 没显式控制、文件后缀或构建规则没对齐,相似类名就可能生成近似哈希,导致样式覆盖。
为什么 button 和 Button 会被编译成几乎一样的哈希
默认情况下,Webpack 的 css-loader(尤其 modules: { auto: true } 模式)只用原始类名 + 文件名生成哈希,不包含路径层级。所以 src/components/Button.module.css 和 src/pages/Button.module.css 中都写 .button,哈希值很可能重复。
- 哈希来源太窄:
[name]__[local]--[hash:base64:5]忽略了目录结构,不同路径下同名文件 → 同哈希 - 大小写敏感但哈希不区分语义:
header和Header在部分配置下可能产出相似后缀 - Vite 用户容易忽略:它默认只认
.module.css,若误用.module.scss且未配 Sass loader,则退化为全局 CSS
必须改的 localIdentName 配置项
这是唯一能从源头杜绝冲突的配置点。不能依赖默认,必须显式声明包含路径、文件名、类名和短哈希的组合模式。
- 推荐值:
[path][name]__[local]___[hash:base64:5](Umi4/Vite/Webpack 均适用) -
[path]确保components/Header.module.css和layouts/Header.module.css绝对隔离 -
[hash:base64:5]长度够短便于调试,又足够唯一;别用:8或:md5——无必要且拖慢构建 - Webpack 项目中,该配置必须落在
css-loader的options.modules下,不是顶层options
Umi4 项目里三步落地小驼峰命名
Umi4 内置 preset 默认不带路径,直接改 .umirc.ts 即可生效,无需动 builder 配置。
立即学习“前端免费学习笔记(深入)”;
- 在
cssLoader.cssModules下设置pattern: '[path][name]__[local]___[hash:base64:5]' - 同时开
camelCase: true,让.btn-primary可通过styles.btnPrimary访问 - 组件内类名保持连字符写法(
.header-title),JS 中用驼峰读取——这是 CSS Modules 规范,不是 TS 类型要求
验证是否真正生效的唯一方式
别信控制台日志或配置文件是否“写了”,打开浏览器开发者工具,看真实 DOM 上的 class 属性值:
- ✅ 正确:
components_Header__title___aBc2d(含路径、双下划线、三段式分隔、短哈希) - ❌ 失效:
header__title___12345(缺路径)、title(纯原始名)、_1a2b3c(旧版默认 hash 格式) - ⚠️ 注意:哈希每次构建都会变,哪怕只改空格——这不是 bug,是内容指纹机制,说明配置已接管编译流程
最常被跳过的环节是路径大小写校验和构建配置嵌套层级。一个 ./Header.module.css 导入语句里字母大小写错一位,或 css-loader 配置多缩进一层,就足以让整个模块化失效——哈希再长也没用,因为压根没走那条编译路径。


















