composes声明必须位于CSS规则体最前面且跨文件引用需带.module.css后缀,否则会被忽略或编译失败;仅支持单类名、禁止空格与伪类,同一文件多类组合用空格分隔,其为编译期合并而非运行时继承。

composes 声明必须放在规则体最前面
如果 composes 写在其他声明(比如 color 或 display)之后,Webpack 的 css-loader 会直接忽略它,不报错也不生效。这是最容易被忽略的硬性规则。
- ✅ 正确写法:
.primaryButton {<br> composes: baseButton from './base.module.css';<br> background-color: #1890ff;<br>} - ❌ 错误写法:
.primaryButton {<br> background-color: #1890ff;<br> composes: baseButton from './base.module.css'; // 被忽略 - 同一文件内组合多个类,用空格分隔:
composes: flex align-center;
跨文件引用必须带 .module.css 后缀
Webpack 的 css-loader 在解析 from 路径时,只认显式带 .module.css 扩展名的模块。漏掉后缀会导致编译失败或静默 fallback 到全局样式,极难排查。
- ✅ 正确路径:
composes: header from './Layout.module.css'; - ❌ 错误路径:
composes: header from './Layout.css';或composes: header from './Layout'; - 相对路径以当前文件为基准,不支持
~别名(除非你额外配了 resolve.alias)
composes 只支持单个类名,不支持选择器或伪类
composes 的设计目标是“类级复用”,不是 CSS 选择器拼接。传入复合选择器、空格、冒号都会导致语法错误或意外行为。
- ✅ 允许:
composes: button from './ui.module.css'; - ❌ 禁止:
composes: .button.primary;、composes: button:hover;、composes: btn primary; - 想实现类似效果?拆成两个独立
composes行,或把组合逻辑提到 JS 层(className={`${style.btn} ${style.primary}`})
composes 是编译期合并,不是运行时继承
它不会生成嵌套规则或增加 specificity,而是把目标类的最终哈希名也注入当前类的输出中。这意味着两个类名都会出现在 DOM 的 class 属性里,且顺序由你在 CSS 中写的先后决定。
立即学习“前端免费学习笔记(深入)”;
- 例如
.btn { composes: base from './base.module.css'; }编译后可能变成:<button class="btn_abc12 base_xyz78"> - 如果
base.module.css里有:global()规则,它也会被正常注入,但不受局部作用域保护 - 调试时注意:DevTools 里看到的类名是哈希值,需对照 source map 或开发模式下的
[name]_[local]格式定位源码
composes 放错位置这两个点。一旦出问题,控制台通常没提示,得靠检查编译后的 CSS 文件内容来确认是否注入成功。


















