必须用@use而非@import,因@import是文本拼接、破坏作用域且引发变量覆盖;@use提供模块化隔离,配合Vite的additionalData可全局注入变量,但需注意插值语法与CSS变量分离。

直接用 _config.scss + @use 是唯一可靠方式,@import 已废弃且破坏作用域,sass-resources-loader 在现代构建工具(Vite / Webpack 5+)中容易引发变量覆盖冲突。
为什么不能用 @import 导入全局变量
@import 本质是文本拼接,不是模块引用。同一文件多次 @import "_config.scss",等于重复声明变量——后一次会覆盖前一次,但顺序取决于导入路径深度,不可控。更严重的是,它绕过 Sass 模块系统,所有变量都注入全局命名空间,一旦两个第三方库定义了同名 $spacing-sm,编译直接报错或静默覆盖。
常见错误现象:Invalid CSS after "$color-primary": expected expression(旧版 Sass 解析失败),或 H5 热更新后某几个组件颜色突然回退。
- 必须用
@use,Sass 1.23+ 才完整支持模块化 -
@use默认启用作用域隔离:变量只在导入它的文件里可见,避免污染 - 要让变量“全局可用”,得靠构建工具注入(如 Vite 的
additionalData)或统一入口@use
@use "config" with () 覆盖默认值的实操要点
当你维护一套可复用的 UI 库(比如 @myorg/ui),下游项目需要微调基础值(如把 $radius-base 从 4px 改成 6px),就得靠 with。但它不是万能的:
立即学习“前端免费学习笔记(深入)”;
- 被覆盖的变量必须在
_config.scss中声明为!default,否则with无效 -
with只接受字面量和已定义变量,不支持表达式:✅ $radius-base: 6px,❌ $radius-base: calc(#{$spacing-xs} * 3) - 只能在项目入口文件(如
main.scss)中写一次@use "config" with (...),其他文件一律用@use "config" - 路径别写错:
@use "@/styles/config"(@/是 Vite 别名)比@use "../styles/config"更稳定
Vite / Vue / uni-app 中如何真正“全局”生效
所谓“所有 .vue 文件都能直接用 $color-primary”,不是靠每个 <style lang="scss"> 里手动 @use,而是靠构建层注入。否则热更新时变量解析顺序错乱,小程序端样式会随机失效。
正确做法是在 vite.config.ts 中配置:
css: {
preprocessorOptions: {
scss: {
additionalData: '@use "@/styles/config.scss" as *;'
}
}
}as * 是关键——它把 _config.scss 里的所有变量、函数、mixin 全部挂到当前作用域,不用写 config.$color-primary。但注意:
-
additionalData是 Vite 特有机制,Webpack 项目得用sass-resources-loader(仅限 Webpack 4/5,且需确保 loader 链顺序正确) - uni-app 必须走
vite.config.ts,sass-resources-loader在小程序平台根本不起作用 - 如果用了
as *,就别在单个文件里再@use同一文件,否则触发重复解析
导出 CSS 自定义属性时的插值陷阱
你可能想在 _config.scss 里同时管理 Sass 变量和对应 CSS 变量,比如:
:root {
--color-primary: #{$color-primary};
--spacing-md: #{$spacing-md};
}这没问题,但必须用 #{} 插值,不能直接写 --color-primary: $color-primary(Sass 不会自动转义)。更隐蔽的问题是:
- Sass 变量和 CSS 变量职责要分离:
_config.scss只管 Sass 层逻辑(计算、条件、函数),CSS 自定义属性应单独抽到_css-vars.scss中生成 - 如果变量含单位(如
$spacing-md: 1.5rem),插值后是合法的 CSS 值;但如果用了函数(如scale-color($color-primary, $lightness: 20%)),插值结果可能含 Sass 函数调用,浏览器无法识别 - 导出 CSS 变量时,别混用
!default和as *注入——前者用于 Sass 层覆盖,后者只是快捷访问,二者不联动
最易被忽略的一点:Sass 模块系统本身不生成任何 CSS,@use 只是加载变量和函数。真正输出 CSS 变量,得靠你在某个根文件里显式写 :root {...},否则光定义没用。


















