被尤雨溪diss的Native CSS Modules是什么
大家好,我是卡頌。
昨天早上正吃著早飯,唱著歌,開開心心摸魚時,看到一條尤大的推文:
尤:老實說,我認為Native CSS Modules標準是倉促的,再次顯示了參與該標準制定過程的人的傲慢
經常看尤大和其他大佬們交流技術,「倉促」、「傲慢」這樣的字眼是很少看到的。
今天我們來看看是什么樣的標準,讓尤大都忍不住diss。
此CSS Modules非彼Modules
想必做前端的同學對CSS Modules不會陌生,這里簡單介紹下。
CSS Modules是一套開源的規范,用以解決CSS的以下問題:
- 命名沖突
- 沒有模塊化
- 依賴關系不明(樣式覆蓋問題)
該規范需要打包工具實現。
我們用一個例子來簡要了解他的實現細節:
將CSS文件style.css引入為style對象后,通過style.title的方式使用title class:
- import style from './style.css';
- export default () => {
- return (
- <p className={style.title}>
- I am KaSong.
- </p>
- );
- };
對應style.css:
- .title {
- color: red;
- }
打包工具會將style.title編譯為「帶哈希的字符串」:
- <h1 class="_3zyde4l1yATCOkgn-DBWEL">
- Hello World
- </h1>
同時style.css也會編譯:
- ._3zyde4l1yATCOkgn-DBWEL {
- color: red;
- }
這樣,就產生了獨一無二的class,解決了CSS模塊化的問題。
而今天的主角,并非這位CSS Modules。
Native CSS Modules
今年6月,谷歌工程師「Justin Fagnani」在推上公布了CSS Modules的最新進展:
此CSS Modules并非上文提到的開源方案,而是ES Modules標準下的一個標準。
該標準實際名稱為CSS Module Scripts,但社區習慣稱其為CSS Modules。
為了與開源方案區別,下文稱其為Native CSS Modules。
該標準用來在JS中導入CSS,語法類似ES Modules:
- // ES Modules
- import React from "https://cdn.skypack.dev/react@17.0.1";
- // Native CSS Modules
- import styleSheet from "./styles.css" assert { type: "css" };
導入的CSS可以應用于document對象或shadow DOM。
導入的styleSheet數據結構如下:
配合Constructable Stylesheets[1]特性,可以解決CSS:
- 在多個shadow DOM之間復用
- FOUC問題(Flash of Unstyled Content,即由于樣式未加載完導致DOM樣式從無到有的閃爍情況)
看起來很nice,那么尤大diss的點在哪里呢?
這么多問題?
首選,通過對比可以發現:
- 該標準命名與現有開源方案沖突
- 標準的語法與現有開源方案語法相同
第一點,假設在未來一個初學者搜索CSS Modules,那么結果可能會讓他困惑,我搜到的是誰?
第二點,當前各大打包工具都有對開源CSS Modules方案的支持。
如果未來需要實現Native CSS Modules的polyfill,輕則造成重復工作、重則遇到兩種方案更迭造成的混亂(想想社區從CJS過渡到ES Modules遇到多少問題)。
除此之外,該方案可能對SSR不友好。
并且,由于Native CSS Modules需要在所屬JS模塊加載后再異步加載,可能會產生很多碎片化的CSS文件請求。
在有如此多潛在問題的情況下,「Justin Fagnani」仍積極推進該標準的落地,可能這就是尤大認為對方「傲慢」的原因吧。
你可以在討論1[2]與討論2[3]看到雙方完整的討論
總結
新的標準,既要在原有基礎上有所突破,又受限于現狀不能大刀闊斧改變。
這種突破與權衡的博弈每時每刻都是開源的世界上演。
參考資料
[1]Constructable Stylesheets:
https://developers.google.com/web/updates/2019/02/constructable-stylesheets[2]
討論1:
https://twitter.com/justinfagnani/status/1403495082506866690[3]
討論2:
https://twitter.com/Joelbdenning/status/1427427564532887565