必须用.module.scss后缀+:export语法,否则js中import进来的对象为空或undefined;因普通.scss文件被css-loader视为纯css,不解析sass变量,而:export仅在css modules模式(即.module.scss)下生效。

直接结论:必须用 .module.scss 后缀 + :export 语法,否则 JS 中 import 进来的对象永远是空的或 undefined
为什么 import styles from './variables.scss' 拿不到变量?
Sass 文件默认编译为 CSS,Webpack 的 css-loader 只会把类名转成哈希、导出一个空对象或局部作用域对象,根本不会解析 $color-primary 这类 Sass 变量。即使你写了 @export $color-primary,普通 .scss 文件也不会触发导出逻辑。
关键点在于::export 是 CSS Modules 的特性,只对启用了 CSS Modules 的文件生效 —— 而 Webpack/Vite 默认只对 .module.scss(或 .module.css)启用该模式。
- ❌ 错误写法:
import vars from './variables.scss'(后缀不是.module.scss) - ✅ 正确写法:
import vars from './variables.module.scss' - ⚠️ 注意:
:export必须写在顶层,不能嵌套在@media或选择器里
:export 的写法与限制
:export 块里只能写键值对,且值必须是字符串、数字、布尔或 null;Sass 变量本身不能直接导出,得先用 #{} 插值转成字符串,或用 inspect() 提取原始值(但注意单位会丢失)。
例如:
// variables.module.scss
:export {
primaryColor: #{$primary-color}; // 编译后变成 "rgb(51, 51, 51)" 或 "#333"
borderRadius: #{$border-radius}; // 变成 "8px"
isDarkTheme: true;
}
- 不支持表达式计算:
#{10px * 2}会报错,:export不执行 Sass 运算 - 颜色值会自动转成 RGB 字符串,如
$primary-color: #007bff→"rgb(0, 123, 255)",不是原始十六进制 - 如果需要保持
#007bff,改用inspect($primary-color),但要注意它可能带引号
TypeScript 中类型缺失怎么办?
TS 编译器不认识 .module.scss 的导出结构,默认认为 import 进来的是 {},访问 vars.primaryColor 会报错。
解决方式只有两个,任选其一:
- 手动创建
variables.module.scss.d.ts,内容为:declare const styles: { primaryColor: string; borderRadius: string; isDarkTheme: boolean; }; export default styles; - 用
/// <reference types="sass-extract-js"></reference>配合构建时生成类型(需额外引入sass-extract-js工具链,适合大型主题系统)
不推荐依赖 typings-for-css-modules-loader:它已多年未维护,与 Webpack 5+ / Vite 兼容性差。
常见错误现象和排查顺序
遇到 vars.primaryColor 是 undefined,按这个顺序检查:
- 文件名是否真的是
xxx.module.scss?拼错后缀(比如.modules.scss少个i)就完全失效 - Webpack/Vite 是否禁用了 CSS Modules?Vite 默认开启,但自定义
css.modules配置可能关掉它 - 有没有多个
:export块?只认第一个,后面的会被忽略 - 变量是否在
:export前已被@import引入?确保$primary-color在当前文件作用域内已定义,而不是只在另一个未被@import的文件里
最隐蔽的坑:Vue 3 + <script setup></script> 下,若 import 写在 defineProps 或 defineEmits 之后,TS 类型推导可能失效 —— 把 import 移到最顶部。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











