CSS in JS 新秀:vanilla-extract 淺析
前言
2021 年,vanilla-extract
作爲黑馬登頂了 css-in-js
滿意度榜首(雖然使用率僅爲 1%),號稱是一個類型安全、高度兼容 TS 場景的庫,國內相關討論還很少,稍微看了一下還挺好用的。
介紹
官方文檔:https://vanilla-extract.style/documentation/
打開vanilla-extract
官網文檔,裏面已經羅列了他的那些優點。作爲一個如果使用 css-in-js
會首選styled-components
的我來說,比較關注的點主要是:
-
All styles generated at build time
-
Type-safe styles via CSSType.
這兩點說白了就是,零運行時且支持typescript
。
-
零運行時:
vanilla-extract
會在編譯時期,編譯出css
modules
值和css
內容,不需要帶任何運行時內容到生產環境,相對來說運行速度更高,產物體積更小; -
typescript:支持
typescript
類型檢查,CSS 安全;
目前,業界大多數相關競品如 styled-components
就是一個運行時方案且基於標籤模板進行書寫,主要基於stylis
解析器解析,如果頻繁更新props
還會造成style
標籤大量插入到head
裏。
安裝
Webpack 環境下,需要同時安裝 @vanilla-extract/css
與 @vanilla-extract/webpack-plugin
插件:
yarn add @vanilla-extract/css @vanilla-extract/webpack-plugin
安裝完成後,修改 Webpack 配置:
const { VanillaExtractPlugin } = require('@vanilla-extract/webpack-plugin')
module.exports = {
entry: './src/index.js',
// ....
plugins: [new VanillaExtractPlugin()]
};
這裏可以看見,當我們使用 vanilla-extract
時,需要安裝兩個庫:
-
@vanilla-extract/css
:開發核心庫,基於該庫進行項目業務樣式開發; -
@vanilla-extract/webpack-plugin
:webpack
插件。前面也提及了vanilla-extract
是一個零運行的庫,主要是通過該插件處理。 -
通過增加
webpack
配置項,對相關後綴文件使用自定義的@vanilla-extract/webpack-plugi/loader
進行處理。 -
在其內部通過
eval
庫在編譯時先執行得到className
結果,避免在運行時執行過程; -
再移除
@vanilla-extract/css
庫,使其不會影響到生產環境下js
包體大小;
構建樣式 API
這裏只會對vanilla-extract
比較核心的構建樣式相關幾個 API 提及,其他API
可以直接前往官網查看。
style
import { style } from '@vanilla-extract/css';
export const parentClass = style({
background: 'red',
':hover': {
background: 'blue',
},
});
export const childClass = style({
selectors: {
'&:nth-child(2n)': {
background: '#fafafa',
},
[`${parentClass} &`]: {
color: 'pink',
},
},
});
import { childClass, parentClass } from './index.styles.css';
const Demo = () => (
<div className={parentClass}>
<div className={childClass}>DEMO1</div>
<div className={childClass}>DEMO2</div>
<div className={childClass}>DEMO3</div>
</div>
);
export default Demo;
這個簡單的demo
我相信,看幾下就已經明白是怎麼使用了。但是需要理解的地方是,爲了提高可維護性,「每個樣式塊只能針對某個元素(或者說是使用這個樣式塊的元素)」。那麼在上述代碼裏的selectors
而言,「其目標必須是」****&
(也就是自身元素)而不能是其他元素。例如:`${parentClass} &`
是 OK 的,但是`& div`
是不允許的。這樣的設計,我覺得更是一種職責分離吧,每個樣式塊都針對某個元素,那麼對於項目而言,樣式的可維護性就大大提高了,相比於其他css
in
js
(styled-components)就不容易出現樣式冗餘的問題。對於一些特殊情況,比如:在寫styled-components
我們會利用其包裹arco
組件(或是其他組件),然後對其內部元素樣式進行覆寫或是新增。
const StyledSelect = styled(Select)`
div {
color: red;
}
`
那麼在vanilla-extract
樣式塊裏是不能直接做到的,因爲每個樣式塊都是針對某個元素,是不能直接通過該樣式塊,直接對其兄弟元素、子元素進行樣式調整。但是,對於這種情況,是可以使用另一個 APIglobalStyle
進行開發。
globalStyle
顧名思義,就是全局樣式 API。但是因爲本身vanilla-extract
走css module
,每個 className 都是獨一無二,那麼通過globalStyle
來對其子元素進行樣式調整覆蓋完全是可行的。
import { style, globalStyle } from '@vanilla-extract/css';
export const parentClass = style({});
globalStyle(`${parentClass} > div`, {
color: 'red'
});
const Demo = () => (
<div className={parentClass}>
<Select/>
</div>
)
相比於 Styled-components 的優點
-
零運行時;
-
樣式開發走 Typescript 安全類型;
-
style 設計職責分離;(當然,styled-components 也是可以的,只是完全取決於看開發者)
-
...
總結
目前瞭解下來,vanilla-extract
是一個總體還不錯的css
in
js
庫,雖然目前使用率比較低,但是後續廠商平臺項目會考慮在一些地方使用看看效果(畢竟不會增大 js 體積)。
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源:https://mp.weixin.qq.com/s/ysjP4JoCDOIXLSXIf3WRpg