@import必然导致CSS重复输出,因其是纯文本插入机制,不识别上下文也不去重,同一文件被多次导入即全量复制多次;必须迁移到@use才能实现单例加载与复用。

重复代码不是编译器“出错”,而是 SCSS 的 @import 机制、@extend 使用方式、或模块加载策略不当导致的必然结果。
为什么 @import 必然导致 CSS 重复输出
@import 是纯文本插入,不识别上下文、不判断是否已加载。哪怕同一份 _variables.scss 被 12 个组件文件各自 @import,它就会被完整复制 12 次——变量声明、@mixin 定义、甚至顶层 CSS 规则(比如 *, ::before, ::after { box-sizing: border-box; })全量展开进每个输出文件。
- 常见现象:打包后 CSS 文件里搜
box-sizing,出现十几处;改一个全局颜色变量,部分页面样式没更新 - 根本原因:Dart Sass 已在 v2.0.0+ 标记
@import为 deprecated,它不具备模块身份,无法去重 - 必须迁移到
@use:同一路径的@use只执行一次,后续引用全部复用内存中的解析结果
@extend 在嵌套中误用会爆炸式生成选择器
@extend 不是“继承样式”,是“合并选择器”。当它出现在嵌套块内,Sass 会把当前完整路径拼上去,而不是只作用于当前选择器本身。
- 错误写法:
.card { @extend %bordered; &__header { color: red; } }→ 只有.card获得%bordered,.card__header不会自动带边框 - 更危险的是:
.modal { .content { %base { ... } } }→ 外部@extend %base会生成.modal .content .alert这种长选择器,而非预期的.alert - 真正安全的
@extend必须满足:占位符扁平定义(%base,非.modal .content %base)、不在@media内声明、且被至少一个@extend显式调用
全局样式注入方式冲突引发隐性重复
Nuxt、Vite 或 Webpack 中,若同时用多种方式引入全局 SCSS,极易触发多轮编译,让同一段 CSS 被塞进最终文件多次。
立即学习“前端免费学习笔记(深入)”;
- 典型组合雷区:
vite.config.ts的additionalData注入了@use "@/styles/index.scss" as *,但又在main.ts或App.vue里写了import "@/styles/index.scss"→ 后者触发第二轮 Sass 编译,完全独立于构建链路 - Nuxt 用户容易踩的坑:
@nuxtjs/style-resources和build.extractCSS: true并存时,若styleResources.scss里用了@import,照样重复;必须确保它只包含@use+@forward - 验证是否成功:编译后打开
dist/style.css,搜索某个唯一规则(如html { scroll-behavior: smooth; }),应只出现一次
最常被忽略的一点:重复往往藏在“看不见”的地方——比如 @use "mixins/flex" 和 @use "src/styles/mixins/flex" 被 Sass 当作两个不同模块加载,路径差异毫秒级就足以绕过单例机制。模块化管不住人,只能靠 lint 规则硬性拦截 @import 和裸 as *。


















