Sass 模組系統:為什麼要拆檔,以及命名空間的概念
樣式檔會長大。一個中型專案的 CSS 動輒三、五千行,全塞在一個檔案裡不是效能問題,是 找不到東西 的問題。Sass 的 模組系統 讓樣式可以拆成幾十個小檔,編譯後再合成一份 CSS。
拆檔要解決的三件事
| 問題 | 模組系統的做法 |
|---|---|
| 檔案太長,改一個按鈕要捲兩千行 | 一個元件一個檔,7-1 架構 |
| 變數與 混入 散落各處,同名互相覆蓋 | 每個模組有自己的 命名空間 |
| 同一個檔案被載入多次,樣式重複輸出 | 每個模組只會被 編譯一次 |
第二、三點是舊寫法 @import 做不到的,也正是模組系統誕生的原因。
模組的成員
一個 .scss 檔案就是一個 模組。它裡面定義的三種東西合稱 成員(member):
// _colors.scss
$brand: #2965f1; // 變數成員
@mixin text-brand { // 混入成員
color: $brand;
}
@function tint($c) { // 函式成員
@return $c;
}
.legacy-banner { // ← 這不是成員,是 CSS 規則
color: $brand;
}成員是給別的檔案用的;CSS 規則則會直接被輸出。 這個區別很重要,一個只放變數與混入的檔案,載入它不會產生任何 CSS。
命名空間
用 @use 載入模組之後,它的成員要加前綴才能存取:
// main.scss
@use "colors";
.btn {
color: colors.$brand;
@include colors.text-brand;
}前綴 colors 就是 命名空間,預設取自檔名(去掉開頭的底線與副檔名)。
好處是一眼看得出來源:colors.$brand 明確指出這個變數來自 _colors.scss。同名也不再打架,colors.$brand 與 theme.$brand 是兩個不同的東西。
命名空間可以改
@use "colors" as c; 縮短前綴,@use "colors" as *; 完全省略。詳細規則見 @use。
私有成員
名稱以 底線或連字號開頭 的成員是私有的,只有定義它的檔案看得到:
// _colors.scss
$_shadow-base: rgba(0, 0, 0, 0.1); // 私有,外部拿不到
$shadow: 0 2px 8px $_shadow-base; // 公開@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 了 colorscolors 被兩條路徑載入,但它 只會執行一次,裡面的 CSS 規則也只輸出一份。@import 在同樣情況下會輸出兩份。
@use 與 @forward 的分工
模組系統只有兩個 at-rule,責任分得很乾淨:
| 用途 | 我自己用得到嗎 | 載入我的人拿得到嗎 | |
|---|---|---|---|
@use | 載入來 自己用 | 是 | 否 |
@forward | 把成員 傳遞出去 | 否 | 是 |
典型的入口檔整份都是 @forward:
// abstracts/_index.scss
@forward "variables";
@forward "mixins";
@forward "functions";其他檔案只要載入這一個目錄就好:
@use "../abstracts" as a;
.card {
padding: a.$gap;
}目錄可以直接載入
@use "../abstracts" 會自動找該目錄下的 _index.scss。這是組織大型專案的標準做法,見 abstracts 該放什麼。
檔案的載入規則
寫 @use "colors" 時,Sass 依序尋找:
colors.scss_colors.scss← 分部檔colors/_index.scss
所以路徑 不寫底線也不寫副檔名。
常見問題
模組系統解決了 @import 的什麼問題?
@import 把所有檔案的變數與混入都倒進同一個全域空間,同名的東西會互相覆蓋,而且同一個檔案被載入多次就會輸出多份樣式。模組系統讓每個檔案有自己的命名空間,也保證每個模組只會被編譯一次。
什麼是模組成員?
一個 Sass 檔案裡定義的變數、混入與函式合稱它的成員。用 @use 載入之後,這些成員要透過命名空間存取,例如 colors.$brand。檔案裡的 CSS 規則不是成員,它們會直接被輸出。
命名空間可以改嗎?
可以。預設是檔名去掉底線與副檔名,用 as 可以改成自訂的短名稱,用 as * 可以完全省略前綴。省略前綴會失去模組系統最大的好處,只建議用在自己維護的少數工具檔上。
@use 和 @forward 該用哪一個?
要在目前這個檔案裡使用某個模組的成員,用 @use;要把其他檔案的成員原樣傳遞出去、讓載入你的人也拿得到,用 @forward。一個聚合用的入口檔通常整份都是 @forward。