哈希冲突说明css modules未生效,根源是localidentname未含[path]导致同名类跨路径哈希重复;必须设为[path]__[name]__[local]___[hash:base64:5],并确保文件名带.module.css后缀、配置嵌套正确、大小写与路径严格匹配。

哈希处理后仍冲突,说明 CSS Modules 的模块化机制根本没生效——不是哈希不够强,而是构建配置、文件命名或使用方式出了问题。
为什么 button 和 Button 编译出相似哈希
默认 css-loader 的 localIdentName 只含 [name]__[local]--[hash:base64:5],完全不包含路径信息。所以:
-
src/components/Button.module.css中的.button -
src/pages/Button.module.css中的.button
两者生成的哈希极大概率重复,因为 [name] 都是 Button,[local] 都是 button,路径被忽略。
必须显式改 localIdentName 为 [path]__[name]__[local]___[hash:base64:5],让路径参与哈希计算。Vite 用户还要确认是否启用了 css.modules.generateScopedName 并设为同值。
className="primary" 硬编码导致样式“消失”
哈希类名(如 Button_primary__abc123)只在 JS 导入对象中存在,DOM 上不会凭空出现 primary 这个 class。
- ❌ 错误:
className="primary"或className={`btn ${isPrimary ? 'primary' : ''}` - ✅ 正确:
className={`${styles.btn} ${isPrimary ? styles.primary : ''}` - ⚠️ 注意:
composes: primary from './Base.module.css'要求Base.module.css文件名带.module.css后缀,否则导入的是全局 CSS,primary不会被哈希,也无法被复用
Vite 或 Webpack 配置未真正接管 .module.css 文件
常见失效场景:
- Vite 项目用了
.module.scss但没配 Sass 插件,结果退化为全局 CSS,class 名原样输出 - Webpack 项目把
modules: { mode: 'local' }写在css-loader顶层options下,而不是嵌套在options.modules里 - Umi4 项目没在
cssLoader.cssModules.pattern中设[path],只改了camelCase - 文件名写成
Button.css而非Button.module.css,构建工具直接跳过 CSS Modules 处理
验证是否生效的唯一方式:打开 DevTools,看真实 DOM 元素的 class 属性值。必须看到含路径片段(如 components_Button__primary___),而非只有 primary___ 或纯原始名。
SSR 或动态渲染时 styles 对象为空
Next.js、RSC 或服务端直出环境里,import styles from './X.module.css' 在 Node 端返回空对象 {},导致客户端 hydrate 时 class 名不一致,样式闪动或丢失。
- 这不是哈希冲突,是模块解析时机问题
- 不能靠改
localIdentName解决,需配合styled-jsx或styled-components的 SSR 支持,或改用getServerSideProps+ 客户端补样式逻辑 - 若坚持用 CSS Modules,需确保所有样式类都在客户端首次挂载后才注入 class,避免服务端渲染出空
class属性
最常被忽略的其实是路径大小写和文件后缀的严格匹配——Components/Button.module.css 和 components/Button.module.css 在 macOS 上可能表现一致,但在 Linux 构建机上会生成不同哈希,导致本地正常、线上冲突。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











