必须用@use而非@import,因其强制模块隔离、避免变量冲突、杜绝重复编译、支持精准命名空间控制,并提升ide跳转准确性;@import则全局污染、覆盖不可控、性能差且已被dart sass 2.0+完全移除。

@use 是当前 Sass 模块化的核心,老项目还在用 @import 的话,复用性会越来越差——变量冲突、重复编译、命名污染,基本是迟早的事。
为什么必须用 @use 而不是 @import
@import 把所有东西塞进全局作用域,就像多人共用一个白板写笔记,谁后写谁覆盖。比如两个文件都定义了 $spacing-sm,你根本不知道最终生效的是哪个值。
@use 则强制模块隔离:每个文件有自己的作用域,默认不暴露任何内容,要导出得显式用 @forward 或 export。这让你能精准控制“谁可以访问什么”。
- 变量不会自动合并或覆盖,冲突从源头消失
- 编译时只加载一次依赖,构建速度明显提升
- IDE 能准确跳转到变量/混合宏定义处,而不是一堆同名结果里猜
@use + @forward 组织基础模块的实操方式
别一上来就拆 50 个文件。先建三个核心模块:_variables.scss、_mixins.scss、_functions.scss,再用 @forward 统一出口。
例如,在 index.scss 中:
@forward 'variables' as var-*; @forward 'mixins' as mixin-*; @forward 'functions' as fn-*;
这样外部只需 @use 'index' as s;,就能用 s.var-primary-color、s.mixin-center-flex,前缀清晰,不会和别的库撞名。
- 所有
@forward都该放在单独的入口文件里,避免分散在各处 - 不要
@forward 'variables' without $font-size;这种精细过滤——除非真有强隔离需求,否则增加维护成本 - 如果某个组件(如
_button.scss)只依赖variables,就只@use 'variables',别全量@use 'index'
混合宏(@mixin)怎么写才真正可复用
可复用的 @mixin 不是把一堆样式打包,而是解决一类参数化问题。比如按钮样式,别只写 @mixin btn-primary,而应抽象成:
@mixin button($bg: $color-primary, $size: 'md', $radius: $border-radius-sm) {
background-color: $bg;
padding: map-get($spacings, $size);
border-radius: $radius;
}
关键点:
- 所有参数带默认值,调用时可只改其中一两个
- 依赖外部变量(如
$spacings)而非硬编码数值,保证和全局设计系统一致 - 避免嵌套过深——
@mixin内部不要出现&:hover嵌套,交给使用者自己组合 - 命名体现意图,而不是实现细节,比如用
@mixin visually-hidden而不是@mixin sr-only(后者是具体技术手段)
老项目迁移时最容易踩的坑
直接全局替换 @import → @use 会报一堆 “undefined variable” 错误,因为 @use 不自动导入依赖链。
- 先给所有被
@import的文件加@use,哪怕只是临时写@use 'variables';在顶部 - 遇到
@extend %placeholder报错?说明占位符没被当前作用域引入——要么把%placeholder移到@use的文件里,要么用@forward 'base' as base-*;导出 - Webpack / Vite 插件若仍用旧版 sass-loader,可能不支持
@use,确认版本 ≥ 1.80.0 - 别忽略
.sass和.scss文件混用问题:@use对语法敏感,统一用.scss
真正的模块化不是文件拆得多,而是每个模块有明确边界、可预测行为、无隐式依赖——这点比语法转换更难,也更重要。











