Skip to content

Sass @forward:把模組聚合成單一入口

Sass @forward 聚合成單一入口

@forward@use 常被搞混,但兩者的差別只有一句話:

@use 是載入來自己用;@forward 是把成員傳遞出去給別人用。

我自己用得到嗎載入我的人拿得到嗎
@use "colors"
@forward "colors"

它要解決什麼

沒有 @forward 的話,每個檔案都得自己知道所有零件的路徑:

scss
// components/_card.scss
@use "../abstracts/variables" as v;
@use "../abstracts/mixins" as mx;
@use "../abstracts/functions" as fn;

三十個元件檔就要重複三十次。有了 @forward,在 abstracts 目錄放一個入口:

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

元件檔就只剩一行:

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

.card {
  padding: a.$gap;
  @include a.center;
}

之後 abstracts 裡新增檔案,只要在 _index.scss 補一行 @forward,三十個元件檔一個都不用改。

自己也要用的話,兩行都要寫

@forward 不會讓自己拿到成員:

scss
// abstracts/_index.scss
@forward "variables";
@use "variables" as v;   // 自己也要用,得再寫一次

.debug-grid {
  outline: 1px solid v.$brand;
}

這兩行並存是完全正常的寫法。

show:只轉發指定的成員

白名單,明確定義這個模組對外的介面:

scss
@forward "button" show $radius, btn-base, is-active;

只有列出的三個成員會傳遞出去,其他都藏起來。變數要寫 $混入函式 直接寫名字。

hide:藏起指定的成員

黑名單,其餘全部轉發:

scss
@forward "button" hide $internal-padding, reset-button;

兩者的取捨

show 讓介面明確,但每加一個成員就要改一次清單;hide 省事,但外面可能拿到你不打算公開的東西。要當成套件給別人用就 show,專案內部自己用 hide 就夠了。

只是想藏一兩個內部工具的話,其實用 私有成員(名稱加底線開頭)更簡單,不必寫 hide

as 加前綴

多個模組聚合到同一個入口時,名稱可能撞在一起。as 加上前綴可以避免:

scss
// _index.scss
@forward "button" as btn-*;
@forward "card" as card-*;
scss
@use "components" as c;

.a {
  @include c.btn-base;    // 來自 _button.scss 的 base
  @include c.card-base;   // 來自 _card.scss 的 base
}

兩個模組都有 base 混入也不會衝突。

轉發時預設值也能改

@forward 也支援 with,用來調整被轉發模組的預設值:

scss
// abstracts/_index.scss
@forward "variables" with (
  $gap: 24px !default
);

結尾的 !default 很重要,它表示「這是我調整過的新預設值,載入我的人仍然可以再覆寫」。省略的話就會寫死,外面就不能再改了。

完整的目錄結構

scss/
├── main.scss
├── abstracts/
│   ├── _index.scss      ← 全是 @forward
│   ├── _variables.scss
│   └── _mixins.scss
└── components/
    ├── _index.scss      ← 全是 @forward
    ├── _button.scss
    └── _card.scss
scss
// main.scss
@use "abstracts" with ($gap: 24px);
@use "base";
@use "components";

入口檔不要寫成 @use

_index.scss 若寫 @use "variables",成員就只有 _index.scss 自己拿得到,外面載入這個目錄什麼都取不到。聚合用的入口檔一律 @forward

檔案怎麼分見 7-1 檔案架構

常見問題

@forward 之後可以在同一個檔案裡用那些成員嗎?

不行。@forward 只負責把成員傳遞出去,自己不會拿到。同一個檔案若也要使用,必須另外再寫一次 @use,兩行並存是正常且常見的寫法。

show 和 hide 差在哪?

show 是白名單,只轉發列出的成員;hide 是黑名單,轉發列出的以外的全部。想明確控制模組對外的介面就用 show,只是要藏掉一兩個內部工具就用 hide

轉發時可以加前綴嗎?

可以,寫成 as btn-* 就會讓所有轉發出去的成員名稱都加上 btn- 前綴。這樣多個模組被聚合到同一個入口時,名稱不會互相衝突。

入口檔要用 @forward 還是 @use?

純粹用來聚合的 _index.scss 應該整份都是 @forward,因為它自己不使用那些成員,只是把它們傳遞給載入這個目錄的人。若寫成 @use,外面的檔案就什麼都拿不到。

延伸閱讀