@import会重复输出CSS是因为它本质是编译时文本展开,每次导入都完整复制文件内容、无去重机制、无作用域隔离、无解析缓存,同一文件导入N次就生成N份相同规则。

因为 @import 是编译时文本展开,每次出现都完整复制目标文件内容,不识别重复、不共享解析结果——哪怕同一文件被导入 20 次,就解析 20 次、展开 20 次、生成 20 份相同 CSS。
为什么 @import 会重复输出同一段 CSS 规则
它不是“加载模块”,而是“粘贴源码”。比如 _reset.scss 里定义了 .sr-only { position: absolute; clip: rect(1px, 1px, 1px, 1px); },只要 5 个组件都写了 @import "reset",最终 CSS 就会出现 5 份一模一样的 .sr-only 规则。
- 没有作用域隔离:所有变量、mixin、CSS 规则全塞进全局,后导入的直接覆盖前一个(比如两个
_vars.scss都定义$color,后者生效但无提示) - 无缓存机制:Dart Sass 对
@import只做文件内容缓存,每次仍要重新解析 AST、展开嵌套、计算@mixin调用 - 路径不校验:写错路径如
@import "mixins"(实际是_mixins.scss),旧版 sass-loader 可能静默忽略,导致变量突然 undefined
@use 为什么能避免重复编译
@use 是符号绑定模型,同一个路径在整个项目中只解析一次,后续调用全部复用已编译的符号表。例如 @use "tokens" as t 在 30 个文件里出现,Sass 编译器只读取、解析、验证 tokens.scss 一次。
- 强制命名空间:
t.$spacing-sm必须带前缀,杜绝冲突,也杜绝意外覆盖 - 按需参与编译:只有真正被引用的变量或调用的 mixin 才进入输出流程;未使用的
@mixin不会展开 - 天然防重复:即使多个模块都
@use "utils",底层模块实例唯一,CSS 规则不会叠加输出
常见误操作让 @use 也变慢
用了 @use 却没提速?大概率掉进了这几个坑:
立即学习“前端免费学习笔记(深入)”;
-
@use "xxx" as *破坏命名空间,编译器退化为类似@import的全局查找模式 - 在 Vite 或 Webpack 的
additionalData里写@use,导致每个 .vue/.scss 文件都独立触发一次模块解析 - 路径用了别名但 loader 不支持(如
@use "@/styles/vars"),sass-loader fallback 到文件系统遍历,I/O 开销飙升 - 把含复杂嵌套或
@extend的样式块塞进@mixin再@use,每次调用仍会复制整块逻辑——这不是@use的问题,是设计误用
真正难的不是把 @import 替成 @use,而是清理掉那些藏在循环里、组件深处、甚至第三方包里的隐式重复导入。它们不会报错,但会让 CSS 体积悄悄翻倍,热更新越来越卡。现在 Dart Sass 已移除 @import,不是警告,是已经不能用了。


















