模組系統正式 推出
由 Natalie Weizenbaum 發佈於 2019 年 10 月 2 日
Sass 團隊多年來都知道,@import
規則,Sass 最早加入的功能之一,並不如我們所願。它給我們的使用者帶來了一連串的 問題。
-
幾乎不可能找出一個給定的變數、Mixin 或函數(統稱為「成員」)最初是在哪裡定義的,因為在一個樣式表中定義的任何內容都可供在其後導入的所有樣式表 使用。
-
即使您選擇明確導入每個定義了您所使用成員的樣式表,您最終也會得到重複的 CSS 和奇怪的副作用,因為樣式表每次導入時都會從頭重新 載入。
-
使用簡潔的名稱並不安全,因為應用程式中其他地方的某些樣式表總是可能使用相同的名稱,從而搞亂您的邏輯。為了安全起見,使用者必須手動為他們定義的所有內容添加冗長、笨拙的 命名空間。
-
函式庫作者無法確保他們的私有輔助函數不會被下游使用者存取,造成混淆和向下相容性的 難題。
-
@extend
規則 可能會影響樣式表中的任何選擇器,而不僅僅是其作者明確選擇要擴展的 選擇器。
我們也知道,我們想要引入的任何替代方案都必須經過精心設計和開發,以確保它能為 Sass 未來的發展提供堅實的基礎。在過去幾年中,我們討論、設計和開發了一個全新的模組系統,它解決了這些問題以及更多其他問題,今天我們很高興地宣布它在 Dart Sass 1.23.0 中可用。
請注意,模組系統*完全向下相容*。沒有任何現有功能被移除或棄用,您目前的 Sass 樣式表將會像往常一樣繼續運作。我們將模組系統設計為與 @import
完全互通,以便樣式表作者輕鬆地逐步遷移到新系統。我們確實計劃最終淘汰 @import
,但在每個人都有機會遷移之後的很久才會 實施。
@use
,模組系統的核心@use
,模組系統的核心 永久連結
@use
規則 是 @import
的主要替代方案:它使另一個樣式表中的 CSS、變數、Mixin 和函數在目前的樣式表中可用。預設情況下,變數、Mixin 和函數在基於 URL 基礎名稱的命名空間中 可用。
@use "bootstrap";
.element {
background-color: bootstrap.$body-bg;
@include bootstrap.float-left;
}
除了命名空間之外,@use
和 @import
之間還有一些重要的 區別:
@use
只會執行一次樣式表並包含其 CSS,無論該樣式表被使用了多少 次。@use
只會讓名稱在目前的樣式表中可用,而不是全 域。- 名稱以
-
或_
開頭的成員在使用@use
時對目前的樣式表是 私有的。 - 如果樣式表包含
@extend
,則該擴展僅應用於它導入的樣式表,而不應用於導入它的 樣式表。
請注意,佔位符選擇器*沒有*命名空間,但它們*確實*遵守 私有性。
控制命名空間控制命名空間 永久連結
雖然 @use
規則的預設命名空間是由其 URL 的基礎名稱決定的,但也可以使用 as
明確地 設定。
@use "bootstrap" as b;
.element {
@include b.float-left;
}
特殊構造as *
也能用於引入頂層命名空間中的所有成員。請注意,如果多個模組公開了同名成員,並使用as *
引入,Sass 將會產生錯誤。
@use "bootstrap" as *;
.element {
@include float-left;
}
設定函式庫設定函式庫永久連結
使用@import
時,函式庫通常透過設定全域變數來覆寫函式庫中定義的!default
變數進行設定。由於在@use
中變數不再是全域的,它支援一種更明確的函式庫設定方式:with
子句。
// bootstrap.scss
$paragraph-margin-bottom: 1rem !default;
p {
margin-top: 0;
margin-bottom: $paragraph-margin-bottom;
}
@use "bootstrap" with (
$paragraph-margin-bottom: 1.2rem
);
這會在評估之前將 bootstrap 的$paragraph-margin-bottom
變數設定為1.2rem
。with
子句僅允許設定在被引入的模組中定義(或轉發)的變數,並且只有當這些變數使用!default
定義時才允許設定,這樣可以保護使用者避免拼寫錯誤。
給函式庫作者的@forward
給函式庫作者的@forward
永久連結
@forward
規則會引入另一個模組的變數、mixin 和函式,作為目前模組公開的 API 的一部分,但不會讓它們在目前模組的程式碼中可見。它允許函式庫作者將他們的函式庫拆分到許多不同的原始碼檔案中,而不會犧牲這些檔案中的局部性。與@use
不同,@forward
不會向名稱添加任何命名空間。
// bootstrap.scss
@forward "functions";
@forward "variables";
@forward "mixins";
可見性控制可見性控制永久連結
@forward
規則可以選擇只顯示特定的名稱
@forward "functions" show color-yiq;
它也可以隱藏那些只想在函式庫內部使用的名稱
@forward "functions" hide assert-ascending;
額外前綴額外前綴永久連結
如果您透過一個整合模組轉發一個子模組,您可能需要為該模組添加一些手動命名空間。您可以使用as
子句來做到這一點,它會為每個被轉發的成員名稱添加一個前綴
// material/_index.scss
@forward "theme" as theme-*;
這樣,使用者可以使用整合模組,並使用範圍明確的名稱來設定主題變數
@use "material" with ($theme-primary: blue);
或者他們可以使用子模組,並使用更簡單的名稱
@use "material/theme" with ($primary: blue);
內建模組內建模組永久連結
新的模組系統也添加了內建模組(sass:math
、sass:color
、sass:string
、sass:list
、sass:map
、sass:selector
和 sass:meta
)來存放所有現有的內建 Sass 函式。由於這些模組通常會以命名空間的方式引入,因此現在使用 Sass 函式而不與純 CSS 函式衝突變得更加容易。
這也使得 Sass 更安全地添加新的函式。我們預計將來會在這些模組中添加一些便利的函式。
重新命名的函式重新命名的函式永久連結
一些函式在內建模組中的名稱與它們作為全域函式時的名稱不同。已經有手動命名空間的內建函式,例如 map-get()
,在內建模組中刪除了這些命名空間,因此您可以直接寫map.get()
。同樣地,adjust-color()
、scale-color()
和 change-color()
現在分別是 color.adjust()
、color.scale()
和 color.change()
。
我們也藉此機會更改了一些容易混淆的舊函式名稱。unitless()
現在是 math.is-unitless()
,而 comparable()
現在是 math.compatible()
。
移除的函式移除的函式永久連結
Sass 的顏色簡寫函式 lighten()
、darken()
、saturate()
、desaturate()
、opacify()
、fade-in()
、transparentize()
和 fade-out()
的行為都非常不直觀。它們不是流暢地縮放相關屬性,而是以靜態量遞增它們,因此對於亮度為 85%
的顏色,lighten($color, 20%)
會返回 white
,而不是返回亮度為 88%
的顏色(更接近全白的 20%
)。
為了幫助我們朝著解決這個問題的方向前進,這些函式(以及 adjust-hue()
)未包含在新內建模組中。您仍然可以透過呼叫 color.adjust()
來獲得相同的效果 — 例如,lighten($color, $amount)
等同於 color.adjust($color, $lightness: $amount)
— 但我們建議盡可能使用 color.scale()
,因為它更直觀。
未來,我們計畫新增 color.lighten()
和類似的函式作為 color.scale()
的簡寫。
meta.load-css()
meta.load-css() 永久連結
新的模組系統帶有一個新的內建 mixin,meta.load-css($url, $with: ())
。此 mixin 會動態載入具有指定網址的模組,並包含其 CSS(儘管其函式、變數和 mixin 不可用)。這是巢狀匯入的替代方案,它有助於解決動態匯入的某些使用案例,而不會產生許多如果可以動態載入新成員會出現的問題。
@import
相容性@import 相容性永久連結
Sass 生態系統不會在一夜之間切換到 @use
,因此在此期間,它需要 與 @import
良好地互通。這在兩個方向上都受到支援。
-
當包含
@import
的檔案被@use
時,其全域命名空間中的所有內容都被視為單個模組。然後,此模組的成員會照常使用其命名空間來引用。 -
當包含
@use
的檔案被@import
時,其公開 API 中的所有內容都會新增到匯入樣式表的全域範圍中。這允許程式庫控制其匯出的特定名稱,即使對於@import
而不是@use
它的使用者也是如此。
為了允許程式庫維護其現有的以 @import
為導向的 API,並在必要時使用明確的命名空間,此提案還新增了對僅對 @import
可見,而對 @use
不可見的檔案的支援。它們寫成 "file.import.scss"
,並在使用者撰寫 @import "file"
時匯入。
自動遷移自動遷移永久連結
與新模組系統的推出同時,我們也推出了一個新的 自動 Sass 遷移工具。此工具可以輕鬆地將大多數樣式表自動遷移以使用新的模組系統。請按照 Sass 網站 上的說明進行安裝,然後在您的應用程式上執行它。
$ sass-migrator module --migrate-deps <path/to/style.scss>
--migrate-deps
旗標 告訴遷移工具不僅遷移您傳遞的檔案,還要遷移它匯入的所有內容。遷移工具會自動選取透過 Webpack 的 node_modules
語法 匯入的檔案,但您也可以使用 --load-path
旗標 傳遞明確的載入路徑。
如果您希望遷移工具在不實際進行變更的情況下顯示它將進行的變更,請同時傳遞 --dry-run
旗標 和 --verbose
旗標,以指示它僅印出將進行的變更而不儲存到磁碟。
遷移程式庫遷移程式庫 永久連結
如果您想遷移一個 Sass 程式庫,讓下游使用者載入和使用,請執行
$ sass-migrator module --migrate-deps --forward=all <path/to/index.scss>
--forward
旗標 會指示遷移工具新增 @forward
規則,以便使用者仍然可以使用單個 @use
載入您的程式庫定義的所有 mixin、變數和函式。
如果您為了避免命名衝突而為程式庫新增了手動命名空間,則如果您傳遞 --remove-prefix
旗標,遷移工具將會為您移除它。您甚至可以選擇只轉發原本具有該前綴的成員,方法是傳遞 --forward=prefixed
。
提交問題提交問題 永久連結
遷移工具是全新的,因此可能還有一些粗糙的邊緣。如果您遇到任何問題,請不要猶豫在 GitHub 上提交問題!
立即試用!立即試用! 永久連結
模組系統是 Dart Sass 1.23.0 的一部分。您可以立即使用以下方式安裝它
$ npm install -g sass
或者,查看 安裝頁面 以了解所有不同的安裝方式!
未來計畫未來計畫 永久連結
Sass 團隊希望允許 @use
和 @import
共存很長一段時間,以幫助生態系統順利遷移到新系統。然而,為了簡潔性、效能和 CSS 相容性,最終目標是完全淘汰 @import
。因此,我們計畫按照以下時間表逐步降低對 @import
的支援
-
在 Dart Sass 和 LibSass 都推出對模組系統的支援後一年 *或* Dart Sass 推出對模組系統的支援後兩年(取較早者)(最遲為 **2021 年 10 月 1 日**),我們將棄用@import
以及可以透過模組進行的全域核心程式庫函式呼叫。 -
在此棄用生效後一年(最遲為 **2022 年 10 月 1 日**),我們將完全放棄對@import
和大多數全域函式的支援。這將涉及所有實作的主要版本發布。
這意味著 @import
和 @use
可以同時使用的時間至少有兩年,實際上可能接近三年。
**2022 年 7 月**: 鑑於 LibSass 在新增對新模組系統的支援之前就被棄用了,棄用和移除 @import
的時間表已被推遲。我們現在打算等到 80% 的使用者都在使用 Dart Sass(以 npm 下載量衡量)之後再棄用 @import
,並在此之後至少等待一年,甚至更久,才會將其完全移除。