SCSS变量仅在编译期生效,无法运行时按需加载;所谓“按需”实为通过拆分变量文件、条件@import及配置additionalData注入,控制哪些变量参与编译并确保覆盖顺序正确。

CSS 本身不支持“按需加载变量”,SCSS 变量只在编译期生效,不存在运行时加载或卸载;所谓“按需”,本质是控制哪些变量参与编译、哪些样式文件被引入。
SCSS 变量不是运行时模块,不能 import/export 或动态加载
SCSS 的 $color-primary、$spacing-sm 等变量在 sass 编译阶段就被替换成具体值(如 #1d4ed8、4px),最终输出的 CSS 里根本不存在变量。因此:
- 无法用
import('./theme-dark.scss')动态切换变量——它只是源码,不产出可执行模块 - 不能靠 Webpack/Vite 的 code-splitting 分割变量本身,只能分割「使用了这些变量的样式块」
- 所有变量必须在编译前就确定作用域和可见性,否则会报
Undefined variable
真正可行的“按需”:拆分变量文件 + 条件导入
把变量按用途拆成独立文件,再在入口或组件级 SCSS 中显式 @import,才能控制哪些变量进入最终 CSS:
-
_variables.scss:基础 token(颜色、断点、字体) -
_theme-light.scss:覆盖部分变量,如$bg-color: #fff -
_theme-dark.scss:另一套覆盖,如$bg-color: #1a1a1a - 组件 SCSS 文件中只
@import '_variables'; @import '_theme-light';,不引入未用主题
⚠️ 注意:@use 替代 @import 后,变量必须通过命名空间访问(如 theme.$bg-color),且 @use 不支持条件导入,所以多主题场景仍推荐 @import + 手动开关。
立即学习“前端免费学习笔记(深入)”;
组件库中变量解耦的关键:避免直接依赖 dist/variables.scss
像 Element Plus、Bootstrap Sass 这类库,其 dist/variables.scss 是构建产物,已混入默认值且路径不稳定。正确做法是:
- 复制一份
node_modules/xxx/src/styles/variables.scss到项目src/styles/vars/element-plus/下自行维护 - 在自定义主题文件中用
@import '../vars/element-plus/variables',而非@import 'element-plus/theme-chalk/src/common/var' - 确保你的
custom-variables.scss在组件样式@import顺序中早于button.scss等,否则覆盖无效
常见错误:@import 'element-plus/theme-chalk/src/button'; 前没导入你自己的变量,导致始终用默认色值。
Vite / Vue CLI 项目中启用变量热更新的硬性条件
改一个 _variables.scss 就要全量重编译?可以优化,但有前提:
- Vite 用户:必须在
vite.config.js中配置css.preprocessorOptions.sass.additionalData注入全局变量,而不是靠@import链式加载 - Vue CLI 用户:在
vue.config.js的css.loaderOptions.sass.additionalData中注入,且该字符串内不能含@import - 两者都要求:所有组件 SCSS 文件里删掉对
_variables.scss的@import,否则会重复定义或冲突
例如注入方式:additionalData: `@import "@/styles/variables.scss";` —— 这样改变量文件时,Vite 才能精准使所有依赖它的组件样式 HMR 生效。
变量本身没有“加载”概念,真正要盯住的是「谁在用它」「何时被编译进哪块 CSS」「是否被其他同名变量覆盖」——这三个环节卡住了,主题切换和体积控制就全失效。


















