打通 CSS 模块化的任督二脉 —— SASS 让你更强!

261 阅读2分钟

大家好,我是前端架构师,关注微信公众号【程序员大卫】免费领取前端精品资料。

一、背景

在前端开发中,模块化可以提高代码的可维护性和复用性。CSS 本身支持模块化,而 SASS 也提供了自己的模块化方案。

1. CSS 的模块化

CSS 通过 @import 指令来实现模块化,但它是运行时的,意味着浏览器在解析 CSS 时才会去加载和应用 @import 的内容。例如:

@import url("common.css");

CSS 的 @import 指令支持 IE8+ 及主流浏览器,兼容性较好。

2. SASS 的模块化

SASS 的模块化是编译时的,它不能直接运行,而是需要先编译成 CSS 后才能被浏览器解析。SASS 提供了 @import@use 两种模块化方式,其中 @use 是官方推荐的方式。

二、CSS 原生模块化

1. 示例演示

1.1 创建 index.html

<!DOCTYPE html>
<html lang="zh">
<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <title>CSS 模块化</title>
  <link rel="stylesheet" href="./css/foo.css" />
</head>
<body>
  Hello World
</body>
</html>

1.2 创建 CSS 文件

/* foo.css */
@import url("common.css");
/* common.css */
body {
  font-size: 50px;
  color: red;
}

最终,页面加载 foo.css 后,也会引入 common.css,使得 body 文字变大且变红。

三、SASS 的模块化

SASS 提供了两种实现模块化的方法:@import@use(官方推荐)。

1. @import 方式

1.1 运行时模块化(类似 CSS 的 @import)

  1. 初始化项目并安装 sass 依赖:
pnpm init
pnpm i sass -D
  1. package.json 中添加 SASS 编译命令:
{
 "scripts": {
   "sass": "sass --watch src/1.scss src/1.css --no-source-map"
  }
}
  1. 创建 SASS 文件 src/1.scss
@import url('abcdefg.css');
  1. 运行 pnpm sass,会生成 src/1.css
@import url('abcdefg.css');

由于 @import 运行时不会检查文件是否存在,即使 abcdefg.css 不存在,编译也不会报错。

1.2 编译时模块化(SASS 内部模块化)

  1. 创建 src/common.scss
$color: red;

* {
 margin: 0;
 padding: 0;
}
  1. 创建 src/foo.scss,并导入 common.scss
@import "common.scss";

body {
 color: $color;
}
  1. 运行 pnpm sass 后,生成的 foo.css
* {
 margin: 0;
 padding: 0;
}

body {
 color: red;
}

2. @use 方式(官方推荐)

SASS 官方不推荐使用 @import,主要因为以下问题:

  • 混淆@import 既可以导入 CSS 文件,也可以导入 SASS 文件,容易造成歧义,影响代码可读性。

  • 变量污染@import 没有作用域隔离,不同文件的变量可能会互相覆盖。例如,如果引入 @import 'common.scss'@import 'var.scss',var.scss 中的变量可能会覆盖 common.scss 中的变量。

  • 缺乏私有性:所有导入的变量都是全局可见的,难以管理。例如,在 common.scss 中定义变量 $jjj: 1,但无法限制其仅在 foo.scss 内部使用,而是会暴露给所有导入的文件。

2.1 @use 的命名空间

foo.scss 中的 @import 改为 @use

@use "common.scss";

body {
  color: $color;
  font-size: $size;
}

此时会报错 Error: Undefined variable.,因为 @use 会为每个模块添加命名空间。命名空间默认与文件名相同(如 common),修改代码如下即可编译成功:

@use "common.scss";

body {
  color: common.$color;
  font-size: common.$size;
}

2.2 自定义命名空间

可以使用 as 关键字自定义命名空间:

@use "common.scss" as theme;

body {
  color: theme.$color;
}

2.3 取消命名空间(不推荐)

可以使用 as * 取消命名空间,使变量直接可用:

@use "common.scss" as *;

body {
  color: $color;
}

但这种方式可能导致变量污染,不建议使用。

四、总结

模块化方式作用特点
CSS @import运行时加载兼容性较好,但性能较低
SASS @import编译时加载无作用域隔离,容易污染全局
SASS @use编译时加载作用域清晰,官方推荐

在现代 SASS 项目中,建议优先使用 @use 进行模块化管理,以保持代码的清晰性和可维护性。