SCSS中@use与@import的区别

17 阅读9分钟

SCSS(Sassy CSS)中@use@import均用于实现样式模块化,实现代码复用,但二者在作用域、加载机制、命名空间等核心特性上差异显著。其中@import是SCSS早期的导入语法,存在全局污染、重复加载等问题,而@use是Sass 3.8+推出的新版模块化语法,旨在解决@import的缺陷,目前已被官方推荐作为首选导入方式,未来@import将逐步被弃用。

一、核心差异对比(表格清晰呈现)

对比维度@import(旧版语法)@use(新版推荐)
作用域全局作用域,导入的变量、混合宏(mixin)、函数会直接注入当前文件的全局作用域,易造成命名冲突和变量污染。局部作用域,导入的内容被封装在独立模块中,需通过命名空间访问,从根本上避免全局污染和命名冲突。
加载机制多次导入同一文件时,会重复加载、重复编译,增加编译时间,可能导致输出CSS冗余。自动实现单例加载,无论导入多少次同一文件,仅加载、编译一次,提升编译效率,避免冗余代码。
命名空间无命名空间,导入的所有成员(变量、mixin等)可直接访问,无需前缀,易引发命名冲突,需通过冗长命名规避冲突。默认以导入文件的文件名作为命名空间,也可自定义命名空间;访问成员时需加上命名空间前缀,可通过as *省略前缀(慎用)。
私有成员支持不支持私有成员,导入文件中所有定义的变量、mixin均可被外部访问,无法实现成员隐藏。支持私有成员,以-_为前缀的变量、mixin视为私有,仅能在定义文件内部使用,外部无法访问,实现更好的封装性。
依赖关系依赖关系混乱,无法清晰判断变量、mixin的来源,不利于大型项目维护和团队协作。依赖关系显式化,通过命名空间可明确知道每个成员的来源,代码可维护性大幅提升,适合大型项目和团队协作。
变量配置通过重定义变量覆盖默认值(需在@import前定义),但全局变量易被意外修改,配置逻辑不清晰。支持通过with语句针对性配置模块变量,不影响全局,配置逻辑更严谨、可追溯。
官方支持已被官方不推荐使用,计划逐步弃用,仅为兼容旧代码保留,部分新特性不支持。官方推荐首选语法,支持所有新特性,是SCSS模块化开发的标准方案,与@forward配合实现更完善的模块化体系。

上述表格已清晰列出@use@import的所有核心区别,接下来我们重点拆解最影响开发效率和代码质量的两个特性——重复加载和命名空间。

二、重点特性详解(重复加载+命名空间)

2.1 重复加载(性能与冗余核心差异)

重复加载是@import最突出的问题之一,会直接影响样式文件性能和代码冗余度,而@use通过单例加载机制完美解决了这一问题。

  • 当使用 @import 导入模块时,如果在多个文件中多次导入同一个文件,会导致重复加载的问题。
  • 这意味着被导入的文件将在每个使用了 @import 的文件中都被加载一次,导致样式表中包含多份相同的样式,从而影响性能和增加文件大小。

我们通过一个实际示例,直观感受重复加载的问题:

// _variables.scss(被重复导入的模块)
$primary-color: #007bff;
$secondary-color: #6c757d;

// styles1.scss
@import 'variables';
body {
  background-color: $primary-color;
}

// styles2.scss
@import 'variables';
button {
  background-color: $secondary-color;
}

示例解析:我们有两个样式文件 styles1.scss 和 styles2.scss,它们分别使用 @import 导入了同一个 _variables.scss 文件。由于 styles1.scss 和 styles2.scss 都导入了 _variables.scss,在编译这两个样式文件时,_variables.scss 将被加载两次。

编译后的结果如下所示:

// 编译后的 styles1.cssbody {
  background-color: #007bff;
}

// 编译后的 styles2.cssbutton {
  background-color: #6c757d;
}

可以看到,虽然编译后的CSS中未直接显示重复的变量定义,但 _variables.scss 中的内容在编译过程中被加载了两次,不仅增加了编译时间,若模块中包含实际样式(而非仅变量),会导致CSS文件中出现多份相同样式,增加文件大小、影响页面加载性能,还可能引发潜在的样式冲突。

而使用 @use 导入方式可以避免重复加载问题,因为它会确保每个模块只加载一次,即使在多个文件中导入。这样可以优化编译性能,并保持样式表的精简和一致性。

2.2 命名空间(避免冲突的核心机制)

@import 没有命名空间机制,这是导致其命名冲突的核心原因;而 @use 内置命名空间功能,可灵活隔离模块成员,提升代码可读性和可维护性,具体分为三种使用场景。

2.2.1 不使用as:直接以文件名作为命名空间

当在 @use 后面直接跟上文件路径,且不使用 as 关键字指定命名空间时,会将导入的模块整体作为一个命名空间,且使用被导入文件的名称作为命名空间标识(省略下划线前缀)。

// _variables.scss
$primary-color: #007bff;
$secondary-color: #6c757d;

// styles.scss
@use 'variables.scss';  // 省略下划线,默认命名空间为variables
body {   
  background-color: variables.$primary-color; // 通过命名空间访问变量
}  
button {   
  background-color: variables.$secondary-color;
}

示例解析:styles.scss 使用 @use 直接导入了 variables.scss 文件,未指定自定义命名空间,因此 _variables.scss 中的所有内容被封装在 variables 命名空间下,访问时需加上 variables.前缀,避免与当前文件的其他变量冲突。

2.2.2 使用as xxx:自定义命名空间

通过 as 关键字可以为导入的模块自定义命名空间,让命名更简洁、贴合业务场景,进一步提升代码可读性。

// _variables.scss(与上例一致)
$primary-color: #007bff;
$secondary-color: #6c757d; 

// styles.scss
@use 'variables.scss' as customVars;  // 自定义命名空间为customVars
body {   
  background-color: customVars.$primary-color; 
}  
button {   
  background-color: customVars.$secondary-color; 
}

示例解析:通过 as customVars 为导入的模块创建了自定义命名空间 customVars,后续访问模块中的变量时,需通过 customVars. 前缀,既避免了命名冲突,又让变量来源更清晰。

2.2.3 特殊情况:使用as * 导入(无命名空间)

如果在 @use 后面使用 as *,表示将导入的模块的所有内容直接合并到当前文件中,不创建任何命名空间,导入的变量、mixin、函数等可直接使用。

// _variables.scss(与上例一致)
$primary-color: #007bff;
$secondary-color: #6c757d;

// styles.scss
@use 'variables.scss' as *;  // 无命名空间,直接合并内容
body {   
  background-color: $primary-color; // 直接访问变量,无需前缀
}  
button {   
  background-color: $secondary-color;
}

注意:这种方式会丧失命名空间的隔离优势,与 @import 类似,易引发命名冲突,仅建议在变量统一管理、无冲突风险的简单场景使用。

三、语法用法补充(其他核心用法)

3.1 @import 其他常见问题

除了重复加载,@import 还存在全局污染、依赖混乱等问题,以下是基础用法回顾及问题总结:

// _variables.scss
$color: red;
$font-size: 16px;

// _utils.scss
$color: blue; // 与variables.scss中的$color重名
@mixin flex-center {
  display: flex;
  justify-content: center;
  align-items: center;
}

// main.scss
@import "./variables";
@import "./utils"; // 重名变量被覆盖
@import "./variables"; // 重复加载,增加编译冗余

.box {
  color: $color; // 输出blue(被utils.scss中的$color覆盖,意外污染)
  font-size: $font-size; // 输出16px
  @include flex-center;
}

编译后CSS:

.box {
  color: blue;
  font-size: 16px;
  display: flex;
  justify-content: center;
  align-items: center;
}

问题总结:@import导入的变量会全局覆盖,重复导入同一文件会重复编译,无法区分成员来源,维护难度高。

3.2 @use 其他优势用法

除了命名空间和单例加载,@use 还支持私有成员、变量配置等优势特性,以下是补充示例:

// _theme.scss
$-private-var: 10px; // 私有变量(仅文件内可用,前缀-/_)
$primary-color: #3498db !default; // 默认变量,可被配置覆盖
$secondary-color: #2ecc71 !default;

// main.scss
// 自定义命名空间为t,并通过with配置变量
@use "./theme" as t with (
  $primary-color: #e74c3c, // 覆盖默认主色
  $secondary-color: #f39c12
);

.box {
  background: t.$primary-color; // 输出#e74c3c(配置后的值)
  color: t.$secondary-color; // 输出#f39c12(配置后的值)
  // margin: t.$-private-var; // 报错:私有变量无法访问
}

编译后CSS:

.box {
  background: #e74c3c;
  color: #f39c12;
}

四、实际开发场景选择建议

1. 优先使用@use的场景

  • 新建SCSS项目:全程使用@use,配合@forward实现模块化拆分(如按变量、mixin、组件拆分文件),提升代码可维护性和可扩展性。
  • 大型项目/团队协作:通过命名空间隔离和显式依赖,避免命名冲突,清晰区分成员来源,降低协作成本和维护难度。
  • 需要封装私有成员:当部分变量、mixin仅需在当前文件使用,无需暴露给外部时,使用@use的私有成员特性,实现代码封装。
  • 使用Sass新特性:@use支持所有Sass新特性(如内置模块导入),而@import不支持部分新特性,无法适配未来升级需求。

2. 临时使用@import的场景

  • 维护旧项目:当项目中大量使用@import,短期内无法全部迁移时,可临时保留,逐步替换为@use,避免影响项目正常运行。
  • 导入纯CSS文件:虽然@use也可导入纯CSS文件,但@import语法更简洁,且无需处理命名空间(仅适用于简单场景)。

五、补充注意事项

  • @use导入文件时,可省略文件扩展名(.scss、.sass),也可省略下划线前缀(如导入_variables.scss,可写为@use "./variables")。
  • @use的as *语法可省略命名空间,直接访问导入的成员,但会丧失命名空间的隔离优势,易引发冲突,仅建议在变量统一管理的简单场景使用。
  • 迁移旧项目时,需注意:@use中以-_开头的变量视为私有,若旧代码中存在此类命名的变量,导入后会无法访问,需修改变量命名或调整访问方式。
  • @use与@forward的配合:@forward用于转发模块成员(不直接使用),适合库开发或入口文件整合;@use用于直接使用模块成员,二者配合可实现更灵活的模块化体系。
  • Sass内置模块(如sass:math、sass:color)需通过@use导入才能使用,无法通过@import导入,这也是官方推荐@use的重要原因之一。

六、总结

推荐使用 @use 来导入模块,以获得更好的模块化支持、性能优化和避免全局污染问题。其核心优势在于局部作用域、命名空间隔离、单例加载、私有成员支持,彻底解决了@import的全局污染、重复加载、依赖混乱等问题,提升了代码的可维护性、可扩展性和协作效率。而 @import 在新版本 Sass 中已不再推荐使用,并且未来可能会被废弃,仅适合临时维护旧项目,新建项目或项目升级时,应优先采用@use + @forward的模块化方案,遵循官方推荐的开发规范,避免后续维护成本增加。