Skip to content

Sass 模組系統:為什麼要拆檔,以及命名空間的概念

Sass 模組系統總覽與命名空間

樣式檔會長大。一個中型專案的 CSS 動輒三、五千行,全塞在一個檔案裡不是效能問題,是 找不到東西 的問題。Sass 的 模組系統 讓樣式可以拆成幾十個小檔,編譯後再合成一份 CSS。

拆檔要解決的三件事

問題模組系統的做法
檔案太長,改一個按鈕要捲兩千行一個元件一個檔,7-1 架構
變數與 混入 散落各處,同名互相覆蓋每個模組有自己的 命名空間
同一個檔案被載入多次,樣式重複輸出每個模組只會被 編譯一次

第二、三點是舊寫法 @import 做不到的,也正是模組系統誕生的原因。

模組的成員

一個 .scss 檔案就是一個 模組。它裡面定義的三種東西合稱 成員(member):

scss
// _colors.scss
$brand: #2965f1;          // 變數成員

@mixin text-brand {        // 混入成員
  color: $brand;
}

@function tint($c) {       // 函式成員
  @return $c;
}

.legacy-banner {           // ← 這不是成員,是 CSS 規則
  color: $brand;
}

成員是給別的檔案用的;CSS 規則則會直接被輸出。 這個區別很重要,一個只放變數與混入的檔案,載入它不會產生任何 CSS。

命名空間

@use 載入模組之後,它的成員要加前綴才能存取:

scss
// main.scss
@use "colors";

.btn {
  color: colors.$brand;
  @include colors.text-brand;
}

前綴 colors 就是 命名空間,預設取自檔名(去掉開頭的底線與副檔名)。

好處是一眼看得出來源:colors.$brand 明確指出這個變數來自 _colors.scss。同名也不再打架,colors.$brandtheme.$brand 是兩個不同的東西。

命名空間可以改

@use "colors" as c; 縮短前綴,@use "colors" as *; 完全省略。詳細規則見 @use

私有成員

名稱以 底線或連字號開頭 的成員是私有的,只有定義它的檔案看得到:

scss
// _colors.scss
$_shadow-base: rgba(0, 0, 0, 0.1); // 私有,外部拿不到
$shadow: 0 2px 8px $_shadow-base;  // 公開
scss
@use "colors";

.a { box-shadow: colors.$shadow; }        // ✅
.b { box-shadow: colors.$_shadow-base; }  // ❌ Error

這讓模組可以有「內部實作細節」,改它不必擔心別的檔案正在用。

一個模組只會編譯一次

main.scss
├── @use "button"   → button 也 @use 了 colors
└── @use "card"     → card 也 @use 了 colors

colors 被兩條路徑載入,但它 只會執行一次,裡面的 CSS 規則也只輸出一份。@import 在同樣情況下會輸出兩份。

@use 與 @forward 的分工

模組系統只有兩個 at-rule,責任分得很乾淨:

用途我自己用得到嗎載入我的人拿得到嗎
@use載入來 自己用
@forward把成員 傳遞出去

典型的入口檔整份都是 @forward

scss
// abstracts/_index.scss
@forward "variables";
@forward "mixins";
@forward "functions";

其他檔案只要載入這一個目錄就好:

scss
@use "../abstracts" as a;

.card {
  padding: a.$gap;
}

目錄可以直接載入

@use "../abstracts" 會自動找該目錄下的 _index.scss。這是組織大型專案的標準做法,見 abstracts 該放什麼

檔案的載入規則

@use "colors" 時,Sass 依序尋找:

  1. colors.scss
  2. _colors.scss分部檔
  3. colors/_index.scss

所以路徑 不寫底線也不寫副檔名

常見問題

模組系統解決了 @import 的什麼問題?

@import 把所有檔案的變數與混入都倒進同一個全域空間,同名的東西會互相覆蓋,而且同一個檔案被載入多次就會輸出多份樣式。模組系統讓每個檔案有自己的命名空間,也保證每個模組只會被編譯一次。

什麼是模組成員?

一個 Sass 檔案裡定義的變數、混入與函式合稱它的成員。用 @use 載入之後,這些成員要透過命名空間存取,例如 colors.$brand。檔案裡的 CSS 規則不是成員,它們會直接被輸出。

命名空間可以改嗎?

可以。預設是檔名去掉底線與副檔名,用 as 可以改成自訂的短名稱,用 as * 可以完全省略前綴。省略前綴會失去模組系統最大的好處,只建議用在自己維護的少數工具檔上。

@use 和 @forward 該用哪一個?

要在目前這個檔案裡使用某個模組的成員,用 @use;要把其他檔案的成員原樣傳遞出去、讓載入你的人也拿得到,用 @forward。一個聚合用的入口檔通常整份都是 @forward

延伸閱讀