import './button.css' 仍污染全局,因普通 css 文件默认非模块化,webpack/vite 将其作为全局样式注入;仅 .module.css(或配置启用)才生成哈希类名如 button_button__kx2f1。

为什么 import './Button.css' 依然污染全局?
因为普通 .css 文件默认不启用模块化,Webpack/Vite 会把它当作全局样式注入 <style></style> 标签。浏览器按 CSS 全局规则匹配,.button 会命中页面里所有 class="button" 的元素——不管它在哪个组件里渲染。
验证方式很简单:打开 DevTools 查看元素的 class 属性。如果还是原始名(如 button),说明 CSS Modules 根本没走通;只有看到类似 Button_button__Kx2f1 这种带文件标识和哈希的类名,才算生效。
- Webpack 项目必须确保
css-loader配置了modules: true - Vite 默认只对
.module.css启用模块化,.css永远全局 - Umi 可通过
cssModulesWithAffix: true改为用.css后缀启用模块化,但需显式配置
Button.module.css 不生效的三个硬伤
styles.button 渲染为空字符串,不是 React 报错,而是构建阶段压根没生成 styles 对象。根本原因就三个:
- 文件后缀不对:必须是
.module.css(或.module.scss,但得配好sass-loader+css-loader?modules) - 导入路径或大小写错误:
import styles from './button.module.css'在 macOS/Linux 下找不到Button.module.css - 在
dangerouslySetInnerHTML里硬写class="button"——模块类名只存在于 JS 对象中,不会自动注入全局样式表
动态拼接 className 时 styles[variant] 是 undefined 怎么办?
CSS Modules 的类名映射在构建期就固定了。styles['large'] 如果没在 .module.css 文件里明确定义为类名,值就是 undefined,不是空字符串。
Orderly React SDK 钩子使用参考指南,包括 useOrderEntry、usePositionStream、useOrderbookStream、useCollateral 等。
别这么写:className={`${styles.button} ${styles[variant]}`,一旦 variant 值不存在,结果就是 class="Button_button__xxx undefined"。
- 安全写法:用可选链或默认值,例如
className={`${styles.button} ${styles[variant] ?? ''}` - 更稳妥的是提前校验:
Object.keys(styles).includes(variant) - 避免运行时拼字符串——模块类名不是“变量”,是编译期确定的静态键值对
:global() 不是补丁工具,乱用反而扩大污染面
:global() 是唯一能“逃逸”模块作用域的方式,但边界必须清晰:
- ✅ 正确场景:
:global(.ant-modal) { z-index: 9999; }(覆盖第三方库)、:global(*) { box-sizing: border-box; }(重置基础样式) - ❌ 错误场景:把整个组件样式包进
:global();在子组件里用它去“修复”父组件没导出的类名;当成 BEM 命名的替代方案 - ⚠️ 注意:
@import './reset.css'进模块文件,导入的仍是全局 CSS,等价于直接写:global(),不是“安全引入”
哈希类名每次构建都变,不是 bug,是设计使然——改一行 CSS 或挪动文件位置都会触发变更。调试时别盯着类名记,要盯 styles 对象的结构和 DevTools 中的实际渲染效果。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!










