根本原因是sass模块作用域默认隔离,@use导入的变量不会自动全局共享,子项目必须显式@use同一路径;混用@import会触发legacy模式致@use失效,且路径大小写敏感、未配includepaths或未发布为npm包均会导致不生效。

为什么 @use 导入的 Sass 变量在子项目里不生效?
根本原因不是导出失败,而是 Sass 的模块作用域机制默认隔离了变量——@use 加载的模块不会自动把变量注入全局,其他文件必须显式 @use 同一路径才能访问。很多团队误用 @import 迁移旧代码,或在多个 @use 中没统一命名空间,导致设计令牌看似“导出”了,实际用不了。
- 检查是否混用了
@import和@use:Sass 6.0+ 已弃用@import,它和@use不兼容,会破坏模块解析 - 确认所有项目都通过相同路径
@use "tokens"(而非相对路径如@use "../shared/tokens"),否则 Sass 视为不同模块 - 如果用了命名空间别名(如
@use "tokens" as t),引用时必须写t.$color-primary,不能直接写$color-primary
怎样让设计令牌真正跨项目复用?
核心是把 tokens 做成可安装的 Sass 包,而不是靠文件拷贝或相对路径引用。Sass 本身不处理包管理,得靠 npm + package.json 的 "sass" 字段配合构建工具链。
- 在 tokens 仓库根目录加
package.json,设"main": "index.scss",并在"sass"字段声明入口:"sass": {"includePaths": ["."]} - 发布到私有 registry 或用
npm link/yarn link调试,子项目执行npm install @myorg/tokens - 子项目中统一用
@use "@myorg/tokens" as tokens,不再依赖文件路径 - 避免在 tokens 包里
@use其他项目私有路径,否则会污染依赖图
@forward 和 @use 混用时为什么令牌丢失?
@forward 只转发模块的公开成员(即未加 ! 前缀的变量/函数),但不会转发命名空间。如果你在 index.scss 里写 @forward "colors" as color-*;,下游仍需通过 tokens.$color-primary 访问——而很多人忘了加命名空间,直接写 $color-primary,结果报错 Undefined variable。
- 转发时别省略
as:用@forward "colors" as color-*;比@forward "colors";更安全,能控制暴露范围 - 被转发的文件里,私有变量要加
!前缀(如$!_internal-base: #fff;),否则会被意外暴露 - 如果下游项目需要解构式使用(如直接
$color-primary),只能改用@use "..." with覆盖默认值,不能靠@forward省略命名空间
Webpack/Vite 里 Sass 加载器找不到 tokens 怎么办?
不是 Sass 语法问题,而是构建工具没把 node_modules 中的 Sass 包路径加入 includePaths。Vite 默认支持,但 Webpack 的 sass-loader 需手动配置。
- Webpack:在
sass-loader的options里加includePaths: [path.resolve(__dirname, "node_modules")] - Vite:确保
vite.config.ts中css.preprocessorOptions.sass包含includePaths: ["node_modules"] - 验证方式:在任意
.scss文件里写@debug list.length(("a", "b"));,如果报错说明 Sass 解析器根本没加载成功 - 注意 Windows 路径分隔符:用
path.posix.join()替代字符串拼接,避免\导致路径解析失败
最常被忽略的一点:Sass 模块系统对大小写极其敏感,哪怕 @use "@myorg/tokens" 和 @use "@MYORG/tokens" 在文件系统里指向同一目录,在 Sass 编译时也被视为两个不同模块——变量不会共享。别指望文件系统宽容,Sass 不认这个。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











