在前端來說,CSS 是一個非常重要的架構,影響著程式的呈現和畫面的呈現。但 CSS 終究不是程式,能做到的事情是有限的。過去到現在有許多技術都想去解決這問題,形成現在生態圈大亂鬥。
微前端中,在選用這些 CSS 的解決方案就要更加小心,畢竟 CSS 是不分作用域的。
這是 JavaScript Module 時代開始後最常見的樣式模組化技術,靜態化打包 CSS,對於微前端應用處理非常友善,有效切割了各種獨立模組。但共用處理效果不好,因為預設是網 head 注入,如果沒有妥善注意設定,很可能就會造成副作用。但基本上生態都是依賴 PostCss 去執行 CSS 的管理方案,內部處理機制已經相當成熟,大部分情境都不太需要擔心。最主流的 CSS Module 解決方案是 Vue 採用的 SFC 樣式注入方案,透過對相同的 Component 標上 hash attribute,確保精準選擇到 className 對象。除了作用域明確切開,對於微前端共用 Component 效果也相當好。這種方式缺點是跨應用共享困難,hash 本身是難以溝通的。
大體上可以知道 CSS Module 可以基於 Component 為單位注入,保障 Scope。但相似的樣式和共用 CSS 的溝通非常差,打包階段沒辦法與其他微前端溝通,完全沒辦法有效益的共用。我只期待未來有可以 merge 這些 CSS 字串的解決方案,或許也是一個不錯的選擇。
最主流的是在 JSX 體系,沒有樣式模板的支持下,想當然爾需要 JS 的動態注入,也是各項方案中同時滿足作用域切分和共享的方案。共享方式便是將 style sheet 當作 cache base 傳遞,這樣就可以共用樣式上的基礎。
我工作上主要採用這一套解決方案,也針對幾個解決方案執行 POC 的測試。
當今最流行,且多生態都支持良好的樣式解決方案,不容易受到框架解決方案限制。但以主流的 Tailwind 來說,它是在打包階段就決定好使用的 CSS,其實就蠻難跨應用去共享使用,效益略微打折。
但如果在微前端中搭配動態渲染引擎,比如 UnoCSS, MasterCSS, TWind 等解決方案,就可以高效率去共用每一個樣式規則,達到共用最佳化的動態處理。但這也是所有解決方案中隔離性最不好的,他沒有任何作用域保護,一旦共用的 Config 設定被修改,就會帶來大範圍的影響,每個應用也不能自定義自己想要的樣式規則,限制上更吃重規範。
除了主流解決方案外,作用域方案大致也可以分門別類幾種模式。
傳統的 CSS 撰寫和 Atomic 基本上都屬於這種,複用容易。但問題在如果沒有嚴謹的規範,容易因為不同的客製化導致相互污染樣式。
如 CSS Module, CSSinJS 等等方式幾乎是預設採用這個方案,有明確的作用域,能有效避免污染問題。然而也正是因為這種隔離,導致共用不易。加上仍然屬於全域 CSS,如果有不當操作依然會發生污染等可能性。
如 iframe, Shadow DOM 都是這種解決方案,直接放棄共用的考慮,徹底執行作用域隔離,真正做到 CSS 作用域隔離的解決方案。不但幾乎無法複用,有些 Library 使用上也可能不支援這個情境,讓開發技術選用上邊的十分不方便。
關於 CSS 解決方案其實可以延伸探討的部分真的太多了,不太是一個文章就能談的很清楚。