四川超宇建设集团有限公司网站jquery素材网站
目录
前言
问题
@import 的缺陷
命名冲突
重复导入
模块系统
@use 规则
@forward 规则
实际修改
前言
最初,Sass 使用 @import 规则通过单个全局命名空间加载其他文件,所有内置函数也可全局使用。由于模块系统(@use 和 @forward 规则)已经推出多年,我们现已弃用 Sass @import 规则和全局内置函数。
@import 会导致许多问题,需要手动为 Sass 成员指定命名空间以避免冲突,当多次导入同一个文件时会减慢编译速度,并且使人类和工具都很难分辨给定变量、混合或函数来自何处。
模块系统修复了这些问题,并使 Sass 的模块化与其他现代语言的最佳实践相媲美,但只要 @import 仍保留在语言中,我们就无法获得它的全部好处。
@import 现在从 Dart Sass 1.80.0 开始已弃用。此外,我们还将弃用 sass: 模块中可用的 Sass 内置函数的全局版本。
问题
将 Sass 升级到 1.80.0 及以上版本后,你可能会遇到如下警告:
WARN  Dart Sass: [file].scss:[line]:8: Sass @import rules are deprecated and will be removed in Dart Sass 3.0.0.
 
该警告表示 @import 规则已被弃用,并且将在 Sass 3.0.0 版本中移除。这看上去很宽容,毕竟 Sass 2.0 还未发布呢。但实际上取代 @import 的现代化方案已经推出好几年了,可它仍然被广泛使用。这大概就是 Sass 在 2.0 之前就弃用它的原因吧。
这个警告是值得修正的,消除它的正面效果绝不仅是清理碍眼的输出。
@import 的缺陷
 
命名冲突
假设我们有以下三个 SCSS 文件:
// file1.scss
$color: blue;
@mixin button {// button styles
}// file2.scss
$color: red; // 会覆盖 file1 的 $color
@mixin button {// 会覆盖 file1 的 button// different button styles
}// main.scss
@import "file1";
@import "file2";
// 此时 $color 是 red, button mixin 是 file2 的版本
 
如上代码中的注释所示,@import 导致了命名冲突。因为 @import 是全局性的,而不是模块化的。对于 IDE 和工具而言也不友好,它们可能很难推断你使用的变量、mixin 等来自哪个文件。全局导入这种东西在现代化语言中不应该存在,或者限制使用。其副作用难以琢磨的。
重复导入
再假设,你有如下文件:
// header.scss
@import "variables";
@import "mixins";// footer.scss
@import "variables"; // 重复导入
@import "mixins"; // 重复导入// main.scss
@import "header";
@import "footer";
// variables 和 mixins 被导入了两次
 
如上代码中的注释所示,@import 会重复导入。因为 @import 并不关心导入的文件是否已经导入过。重复导入会降低编译速度,在大型项目中尤为明显。
模块系统
@use 规则
 
基于 @import 的全局导入特性,我们很容易将变量集中到某个文件中然后直接引入到当前的代码环境中:
// app.scss
@import "vars/colors";h1 {color: $title-color; // <- 直接使用 var/colors.scss 中的变量
}
 
将以上的 @import 改为 @use,现在 Sass 会为我们自动创建命名空间。以避免全局带来的冲突和污染:
// app.scss
@use "vars/colors";h1 {color: colors.$title-color; // <- 使用命名空间访问 var/colors.scss 中的变量
} 
注意,这会带来一个显著的迁移难题。首先,我们以及工具都可能很难推断此前代码中直接使用的变量来自哪里(换作模块化系统就是哪个命名空间),尤其是组织不严谨的项目。该如何准确修改呢?好办:
// app.scss
@use "vars/colors" as *;h1 {color: $title-color; // <- 直接使用 var/colors.scss 中的变量
}
 
as 语法和 *,将所有成员直接导入进来。类似于 JS 的 import *。这样可以让我们的代码平缓迁移,逐渐的改用为命名空间。并且不存在全局范围带来的各种问题。
@forward 规则
 
仅靠 @use 带来的模块化改变,有时候也会增加更多的样板代码。例如你有一批变量文件,按类型归类如 colors.scss、fonts.scss、sizes.scss 等。你需要在每一个使用变量的文件中分别导入它们。
组件 1:
// compoent1.scss
@use "vars/colors";
@use "vars/fonts";
@use "vars/sizes";// compoent1 代码...
 
组件 2:
// compoent2.scss
@use "vars/colors";
@use "vars/fonts";
@use "vars/sizes";// compoent2 代码...
 
使用 @forward 改善这一情况:
// vars.scss
@forward "colors";
@forward "fonts";
@forward "sizes";// 更多的变量文件...
 
然后我们仅导入 vars 即可:
// compoent1.scss
@use "vars";// component2.scss
@use "vars";
 
@forward规则用于将一个模块的内容“转发”到另一个模块中。这样,你可以在不直接使用模块的情况下,通过转发的模块间接使用原始模块的内容。
Sass 为我们提供了迁移工具 sass-migrator,通过它可以自动化的将样式代码迁移到模块化系统。运行命令:
px sass-migrator module --verbose --migrate-deps styles.scss
 
把 styles.scss 替换为你的入口样式文件即可。其中 --migrate-deps 参数表示不仅是修改显式传递给命令行的样式文件,还会修改它的依赖。基于模块系统章节的基本知识,你应该对修改会具有一些审查能力。
实际修改
1. Sass @import rules are deprecated and will be removed in Dart Sass 3.0.0
sass 1.80 不再支持 @import 需要使用 `@use’
- 错误提示:
 
Deprecation Warning on line 1, column 9 of src\About.vue:
Sass @import rules are deprecated and will be removed in Dart Sass 3.0.0.More info and automated migrator: https://sass-lang.com/d/import╷
1 │ @import "@/variables.scss";│         ^^^^^^^^^^^^^^^^^^
 
- 修改方法:
 
@use "@/variables.scss";
 
Deprecation Warning: The legacy JS API is deprecated and will be removed in Dart Sass 2.0.0.
sass 1.80 不再支持老的 js api 接口
- 错误提示:
 
Deprecation Warning: The legacy JS API is deprecated and will be removed in Dart Sass 2.0.0.More info: https://sass-lang.com/d/legacy-js-api
 
- 修改方法 
vue.config.js: 
export default defineConfig({...css: {preprocessorOptions: {scss: {api: 'modern-compiler', // 修改api调用方式},},},...
});
 
Internal server error: [sass] Undefined variable.
sass 1.80 全局变量和 mixin 需要手动导出
- 错误提示:
 
14:20:18 [vite] Internal server error: [sass] Undefined variable.╷
13 │   color: $color-blue;│          ^^^^^^^^^^^
 
14:18:52 [vite] Internal server error: [sass] Undefined mixin.╷
6 │     @include func(css);│     ^^^^^^^^^^^^^^^
 
- 修改方法 
vue.config.js: 
export default defineConfig({...css: {preprocessorOptions: {scss: {api: "modern-compiler",javascriptEnabled: true, // 启用javascriptadditionalData: '@use "@/style/variable.scss" as *;',},},},...
}); 
