根本原因是@use默认启用模块私有作用域,变量必须显式通过命名空间访问(如v.$primary-color),而非自动注入全局;文件须以下划线开头(如_variables.scss),否则被误作入口文件重复编译。

直接说结论:重复变量和重复 mixin 不是“写多了”,而是模块引入方式失控 + 命名空间缺失导致的编译期污染。核心解法就两条——统一入口收口、强制命名空间访问。
为什么 @use "variables" 后 $color-primary 报错找不到
这不是路径或拼写问题,是 Dart Sass 的模块作用域机制在起作用。@use 默认不注入变量到全局,你得显式访问。
- 错误写法:
@use "variables"→ 然后直接写color: $primary-color,报Undefined variable - 正确写法:
@use "variables" as v→ 再写color: v.$primary-color - 别用
@use "variables" as *提升全部变量,它会破坏模块边界,一旦两个模块都定义了$spacing,就会冲突且难以定位 - 所有变量文件必须以下划线开头(如
_variables.scss),否则 Sass 会把它当入口文件单独编译,造成重复输出 CSS
为什么同一个 @mixin 在多个文件里 @include 就生成 12 份 display: flex
@mixin 是编译期展开,不是运行时引用。每次 @include 都会把整个 mixin 内容原样复制一遍,参数不同就生成不同规则,参数相同也照样复制 —— Sass 不合并、不 dedupe。
- 典型诱因:在
_buttons.scss、_cards.scss、_forms.scss里各自@use "mixins" as m,再各自@include m.flex-center - 解决方案:把纯布局类 mixin(如
flex-center、sr-only)改写成原子 CSS 类,用 PostCSS 插件(如postcss-atomic)生成,再交给purgecss裁剪 - 视觉型 mixin(如
btn-variant)保留,但必须只在真正需要差异化的地方调用;共性部分抽成 CSS 自定义属性,比如--btn-padding+ 单一类名.btn - 禁用在
@each循环里@include含选择器的 mixin,那等于批量生成冗余规则
如何让 _variables.scss 和 _mixins.scss 真正成为单一可信源
关键不在“有没有”,而在“谁有权修改”和“谁负责消费”。老项目常犯的错是每个子模块都自己 @use "variables",结果改个 $radius-sm 得 grep 全局。
立即学习“前端免费学习笔记(深入)”;
- 建一个
_tokens.scss作为唯一变量源,只放颜色、断点、z-index、字体阶梯等稳定值;其他文件一律@use "tokens" as t -
_mixins.scss只封装行为逻辑,不硬编码值:@mixin btn-variant($bg: t.$primary),而不是@mixin btn-variant($bg: #007bff) - 禁止跨模块
@use局部样式文件(如_header.scss)—— 它们只应被main.scss统一导入,避免循环依赖 - 用
@debug检查是否意外引入:在_mixins.scss开头加@debug "Loaded mixins module";,编译时看是否重复打印
最容易被忽略的是:变量和 mixin 的复用价值,不取决于你写了多少,而取决于你能否让团队成员在不翻文档、不问人的情况下,一眼看出该用哪个、怎么用、用错了会怎样。命名空间不是束缚,是接口契约。


















