必须用 @use 而不是 @import:@import 会重复展开变量导致覆盖混乱,HMR 和真机表现异常;正确写法是 additionalData: "@use \"@/styles/variables.scss\" as *;",确保只加载解析一次。

additionalData 必须用 @use 而不是 @import
用 @import "@/styles/variables.scss" 会导致变量文件被多次展开,每次 @import 都是文本复制,组件越多,$primary-color 就被重复定义越多遍。SCSS 规则“后定义覆盖前定义”,而 Vite 编译顺序不固定,最终变量值取决于哪个组件最后编译——这就是 HMR 后颜色忽明忽暗、小程序真机表现不一致的根源。
正确写法只有一条:additionalData: `@use "@/styles/variables.scss" as *;`。它不展开内容,而是建立模块引用关系,as * 把所有导出成员平铺进当前作用域,但只加载一次、解析一次。
- 路径必须带
@/别名,且vite.config.ts中resolve.alias已正确定义到src - 字符串必须用反引号(
`)包裹,避免引号和换行出错 - 末尾必须有分号(
;),否则下一行样式会拼成非法语句,报Invalid CSS after "..."
variables.scss 文件里只能放声明,不能写 CSS 规则
additionalData 注入的内容会拼在每个 块开头。如果 variables.scss 里写了 body { margin: 0; } 或 .reset { padding: 0; },这些规则就会在每个组件样式顶部重复出现——构建后生成几十份一模一样的重置代码,体积膨胀、权重混乱、审查元素时满屏重复。
这个文件本质是 Sass 模块(module),只允许:
-
$color-primary: #409eff;(变量) -
@mixin flex-center { ... }(混合宏) -
@function px2rem($px) { ... }(函数)
禁止:@debug、@warn、中文注释、BOM 头、未闭合注释、@forward 未导出的符号。
全局基础样式(reset/base)必须显式导入,不能塞进 additionalData
additionalData 只对 lang="scss" 的样式块生效,对纯 .css 文件、(无 lang)、甚至 完全无效。你往里面硬塞 @use "@/styles/reset.scss" as *;,等于白写。
真正要引入全局重置或基础样式,必须显式导入:
- 在
main.ts里import "./styles/reset.scss" - 或在
App.vue的顶层
千万别在多个组件里各自 @use "@/styles/reset.scss"——这又回到重复注入的老问题,而且 reset 通常含 !important 和高权重选择器,多次打包极易互相覆盖。
CSS Modules 下变量不自动继承,需手动处理
像 Button.module.scss 这类文件默认启用 CSS Modules,它的作用域是隔离的。additionalData 注入的变量虽存在,但不会自动进入模块作用域——你在里面直接写 $primary-color,依然会报 Undefined variable。
解决办法只有两个:
- 在该文件顶部手动加
@use "@/styles/variables.scss" as *;(推荐,明确可控) - 或者改用普通
.scss后缀 +lang="scss",放弃模块化(适合纯样式工具类)
注意:as * 在模块文件里仍可用,但它只影响当前文件,不会污染其他模块——这点比旧式 @import 安全得多。
最易被忽略的一点:所有 @mixin 和 @function 必须集中在一个入口文件(比如 src/styles/index.scss)里统一 @use 和导出,不能散落在各处再靠 additionalData 直接拉进来。否则构建时提取顺序不可控,Undefined mixin 不是配置问题,是代码组织逻辑崩了。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











