Skip to content

Sass @import 為何被棄用,以及遷移到 @use 的做法

Sass @import 棄用與遷移到 @use

@import 是 Sass 最早的拆檔方式,用了將近十年。Dart Sass 已經正式把它 標記為棄用,編譯時會出現警告,未來的主要版本會移除。理由不是為了追新,是它有四個修不好的問題。

它的四個問題

一、全域汙染。 所有被載入檔案的成員都會倒進同一個空間:

scss
@import "colors";   // 裡面有 $brand
@import "theme";    // 裡面也有 $brand

.btn { color: $brand; } // 是哪一個?看載入順序

後載入的悄悄蓋掉前面的,不會有任何警告。

二、看不出來源。 一份三千行的專案裡看到 $gap,你無從得知它定義在哪個檔案,只能全域搜尋。@usev.$gap 直接寫著答案。

三、重複輸出。 同一個檔案被載入兩次,裡面的 CSS 規則就輸出兩份:

scss
// _card.scss 有 CSS 規則
@import "card";  // 在 a.scss
@import "card";  // 在 b.scss → 樣式出現兩次

@use 保證每個模組 只編譯一次

四、無法有私有成員。 所有東西都是公開的,模組寫不出「內部實作細節」。

CSS 的 @import 不受影響

被棄用的只有 Sass 拿來載入 .scss 的那種。下面這些是 CSS 本身的語法,Sass 會原樣輸出:

scss
@import "https://fonts.googleapis.com/css2?family=Noto+Sans+TC";
@import "theme.css";
@import url("print.css") print;

判斷規則:指向網址、以 .css 結尾、帶 url()、帶媒體查詢條件 的都是 CSS 的 @import

CSS 的 @import 本身有效能代價

它會讓瀏覽器多一次串聯請求,阻塞渲染。字型與樣式請盡量改用 HTML 的 <link>,見 CSS 效能優化

用 sass-migrator 自動遷移

官方提供遷移工具:

bash
npm i -g sass-migrator
sass-migrator module --migrate-deps src/scss/main.scss
參數說明
module執行 @import@use 的遷移
--migrate-deps連同相依的檔案一起改
--dry-run --verbose只印出會改什麼,不實際寫入
--forward=all遇到入口檔時改寫成 @forward

它會自動改寫載入語句、補上命名空間前綴、處理跨檔案的相依關係。

一定要先 dry-run,改完要比對產出

先用 --dry-run --verbose 看它打算怎麼改,實際執行後把遷移前後的 CSS 產出做 diff。工具處理不了的通常是動態組出來的路徑,以及靠載入順序覆寫變數的地方。

手動遷移的四個步驟

一、把載入語句換掉。

scss
@import "abstracts/variables";  // 之前
@use "abstracts/variables" as v; // 之後

二、幫所有成員補上前綴。

scss
padding: $gap;    // 之前
padding: v.$gap;  // 之後

三、每個檔案都要自己載入它需要的模組。 這是遷移時最常見的錯誤來源,@import 時代成員全在全域,任何檔案都拿得到;改成 @use 之後,用到 v.$gap 的檔案就必須自己寫 @use "abstracts/variables" as v;

四、把「先宣告變數再載入」改成 with

scss
// 之前
$radius: 999px;
@import "button";

// 之後
@use "button" with ($radius: 999px);

同時要在 _button.scss 裡幫 $radius 加上 !default,否則 with 會失敗,見 變數旗標

分批遷移的策略

大型專案不必一次改完,@use@import 可以共存一段時間:

  1. 先建立各目錄的 _index.scss,用 @forward 聚合。
  2. 從最底層的 abstracts 開始改,那裡沒有相依。
  3. 一個目錄一個 PR,每次都比對編譯產出。
  4. 最後才改進入點。

順手把 node-sass 換掉

還在用 node-sass 的專案根本無法使用 @use(LibSass 不支援)。遷移前先換成 sass,見 安裝與編譯

常見問題

@import 現在還能用嗎?

還能編譯,但 Dart Sass 已正式標記為棄用並會輸出警告,未來的主要版本會移除。新專案不該再使用,既有專案應該排時間遷移。

CSS 原生的 @import 也被棄用了嗎?

沒有,被棄用的只是 Sass 用來載入 .scss 檔的那個 @import。指向網址或以 .css 結尾的 @import 是 CSS 本身的語法,會被原樣輸出交給瀏覽器處理,不受影響。

有工具可以自動遷移嗎?

有,官方提供 sass-migrator。用 npm 安裝後對進入點執行 module 遷移,它會自動把 @import 改成 @use、補上命名空間前綴,並處理跨檔案的相依。改完務必比對編譯結果再提交。

遷移後為什麼會出現找不到變數的錯誤?

因為 @import 時代所有成員都在全域,任何檔案都拿得到;改成 @use 之後每個檔案都必須自己載入它需要的模組。解法就是在該檔案最上方補上對應的 @use

延伸閱讀