宣布 Parcel CSS:一個用 Rust 編寫的新 CSS 解析器、編譯器和壓縮器!
我很興奮地宣布 @parcel/css,一個用 Rust 編寫的新 CSS 解析器、編譯器和壓縮器!在 GitHub 上查看它,或在您的瀏覽器中嘗試 線上示範。
Parcel CSS 的效能顯著優於現有的工具,同時也提升了壓縮品質。除了壓縮之外,Parcel CSS 處理編譯 CSS 模組、tree shaking、自動為您的瀏覽器目標加入和移除供應商前綴,以及轉譯巢狀、邏輯屬性、4 級顏色語法等現代 CSS 功能,還有更多。
它可以用於 Parcel,作為 JavaScript 或 Rust 的獨立函式庫,或包裝為任何其他工具中的外掛程式。Rust 函式庫被設計為 CSS 工具的平台,可以存取所有 CSS 規則、選取器、屬性和值的完整解析資料結構。
效能
#Parcel CSS 非常快。它的壓縮速度比 CSSNano 快 100 倍,比 ESBuild 快 3 倍以上。它可以在單一執行緒上每秒壓縮超過 270 萬行程式碼。此範例顯示一個基準測試,它壓縮了大約 10,000 行的 Bootstrap 4。
儘管速度非常快,但 Parcel CSS 沒有在大小上妥協。在許多情況下,它可以產生比其他工具更小的輸出,這要歸功於它將許多函式庫中使用的舊版 CSS 語法轉換為更小的現代語法,以及它對每個個別 CSS 屬性的完全理解。
Parcel CSS 不僅因為是用原生語言撰寫而快速,還因為它從一開始就以效能為考量進行設計。它在記憶體使用方式上經過最佳化,例如使用單位元組旗標來表示供應商前綴,以及將所有 CSS 屬性解析為結構化資料,而不是將它們表示為每次使用時都需要重新解析的字串。
架構
#Parcel CSS 以 cssparser Rust 箱子為基礎,這是 Mozilla 建立並用於 Firefox 的瀏覽器等級 CSS 分詞器。這提供了穩固的基礎,包括分詞和基本解析。但它不會詮釋任何 CSS 屬性或規則。這就是 Parcel CSS 發揮作用的地方。它會處理解析每個個別規則和屬性值,以及縮小、編譯和列印回 CSS。
許多其他 CSS 處理器將屬性值視為字串,或未分型的代幣系列。這表示每個想要使用這些值的轉換器都必須自行解析和詮釋它們,導致重複工作和不一致。例如,PostCSS 解析的 CSS 屬性 AST 如下所示
{
"type": "decl",
"prop": "background",
"value": "url(img.png) 20px 10px / 50px 100px"
}
即使您使用許多 PostCSS 外掛程式用來對屬性值進行分詞的獨立函式庫 postcss-value-parser
,每個代幣的意義仍然未被詮釋。上述值會解析如下
[
{
type: 'function',
value: 'url',
nodes: [ { type: 'word', value: 'img.png' } ]
},
{ type: 'space', value: ' ' },
{ type: 'word', value: '20px' },
{ type: 'space', value: ' ' },
{ type: 'word', value: '10px' },
{ type: 'div', value: '/' },
{ type: 'word', value: '50px' },
{ type: 'space', value: ' ' },
{ type: 'word', value: '100px' }
]
雖然比字串更具結構化且更容易處理,但並不清楚 20px
是 background-position-x
的值,而 50px
是背景寬度的值。這必須由使用者詮釋。
Parcel CSS 使用 CSS 規格中的語法解析所有值,並為每個屬性公開特定的值類型。例如,Parcel CSS 會將上述屬性表示如下
Background([Background {
image: Url(Url { url: "img.png" }),
color: CssColor(RGBA(RGBA { red: 0, green: 0, blue: 0, alpha: 0 })),
position: Position {
x: Length(Dimension(Px(20.0))),
y: Length(Dimension(Px(10.0))),
},
repeat: BackgroundRepeat {
x: Repeat,
y: Repeat,
},
size: Explicit {
width: LengthPercentage(Dimension(Px(50.0))),
height: LengthPercentage(Dimension(Px(100.0))),
},
attachment: Scroll,
origin: PaddingBox,
clip: BorderBox,
}])
這正是瀏覽器解析 CSS 的方式。值會被詮釋,並填入背景附加等隱含的預設值。這會改善效能,因為每當轉換器想要對屬性做些什麼時,它不需要重新解析、轉換和再次字串化它。這也會改善可靠性,因為每個轉換器不會以稍微不同的方式解析值,或使用正規表示法或字串替換等捷徑,這可能會導致錯誤。
由於屬性值是個別詮釋的,因此這種方法也能夠進行更好的縮小化。例如,隱含的預設值可以自動移除,不需要的空白可以移除,長寫屬性可以在可能的情況下合併為簡寫等。
這個架構提供了 CSS 工具的基礎,這些工具可以專注於以有趣的方式使用屬性,而不是解析和詮釋它們。
試試看
#如果您使用 Parcel,您可以嘗試使用 Parcel CSS 作為您的 CSS 轉換器、縮小器,或兩者。我們希望很快就能取代預設的 CSS 轉換器和縮小器,但想先取得回饋。現在,只要將以下內容新增到您的 .parcelrc
檔案中
{
"extends": "@parcel/config-default",
"transformers": {
"*.css": ["@parcel/transformer-css-experimental"]
},
"optimizers": {
"*.css": ["@parcel/optimizer-css"]
}
}
您也應該將 browserslist
屬性新增到您的 package.json,這會定義您的 CSS 將編譯的目標瀏覽器。
雖然 Parcel CSS 處理了最常用的 PostCSS 外掛程式,例如 autoprefixer
、postcss-preset-env
和 CSS 模組,但您可能仍然需要 PostCSS 來使用更多自訂外掛程式,例如 TailwindCSS。如果是這樣,只要在 @parcel/transformer-css-experimental
之前新增 @parcel/transformer-postcss
,您的 PostCSS 設定就會自動選取。您可以從您的 PostCSS 設定中移除上面列出的外掛程式,它們會由 Parcel CSS 處理。
如果您沒有使用 Parcel,您仍然可以嘗試 Parcel CSS。您可以使用 JavaScript API 獨立使用它,或為您最喜愛的建置工具建立外掛程式。我們希望 Parcel CSS 能被許多工具採用,而不仅仅是 Parcel,這樣我們就能推動整個 CSS 工具生態系統向前發展。
您也可以試試 parcel_css Rust 箱子,它讓您可以完全存取已剖析的 AST,並允許您建置自訂工具。更多 API 文件即將推出,但目前,您需要從 StyleSheet API 開始。請注意,儘管 JavaScript API 是穩定的,但 Rust API 仍處於 alpha 階段,而且隨著我們持續改進 Parcel CSS,結構可能會在不同版本之間變更。
請讓我們知道進展如何!您可以在 GitHub 上提交錯誤或功能要求。