重構 CSS:簡介(第 1 部分)

已發表: 2022-03-10
快速總結 ↬ CSS 重構不是一件容易的事——它需要以一種不會產生問題的方式來完成。 首先,我們需要分析現有的代碼庫,審核 CSS 代碼庫的健康狀況,發現弱點,就方法達成一致,並說服管理層在流程中投入時間和資源。

CSS 是一種簡單的樣式表語言,用於定義網站或文檔的呈現方式。 然而,這種簡單性為許多潛在問題和技術債務敞開了大門——臃腫的代碼、特異性地獄、幾乎沒有區別的重複代碼塊、剩餘的未使用選擇器、不必要的黑客攻擊和變通方法等等。

這種技術債務如果不按時償還,可能會累積並導致嚴重的問題。 最常見的是,當添加新的 UI 組件並使代碼庫難以維護時,它可能會導致意想不到的副作用。 您之前可能參與過一個 CSS 代碼庫很差的項目,並考慮過如何以不同的方式編寫代碼,從而有機會從頭開始重構或重寫所有內容。

無論如何,重構大部分 CSS 代碼都不是一件容易的事。 有時,這似乎只是“刪除質量差的代碼,編寫更好的 CSS,並部署閃亮的改進代碼”的情況。 但是,還有許多其他因素需要考慮,例如重構實時代碼庫的難度、預期持續時間和團隊利用率、確定重構目標、跟踪重構效果和進度等。還有說服管理層或項目利益相關者的問題將時間和資源投入到重構過程中。

在這個由三部分組成的系列中,我們將從頭到尾介紹 CSS 重構過程,首先了解如何處理它以及重構的一些一般優缺點,然後再討論重構策略本身並結束有一些關於 CSS 文件大小和性能的一般最佳實踐。

部分:CSS 重構

  • 第 1 部分: CSS 重構:簡介
  • 第 2 部分:CSS 重構:策略、回歸測試和維護
  • 第 3 部分:CSS 重構:優化大小和性能
  • 訂閱我們的電子郵件通訊,不要錯過下一個。

劣質 CSS 的副作用

儘管 CSS 具有靈活性和簡單性,但它本身存在一些基本問題,這些問題首先允許開發人員編寫低質量的代碼。 這些問題源於它的特殊性和繼承機制,在全局範圍內運行,源順序依賴等。

在團隊層面,大多數 CSS 代碼庫問題通常源於不同的技能水平和 CSS 知識、不同的偏好和代碼風格、對項目結構和現有代碼和組件缺乏了解、缺乏項目層面或團隊級標準和指南等。

因此,質量差的 CSS 可能會導致超出簡單視覺錯誤的問題,並可能產生各種嚴重的副作用,從而影響整個項目。 一些這樣的例子包括:

  • 由於開發團隊中不同的 CSS 技能水平以及缺乏內部規則、約定和最佳實踐,隨著更多功能的添加而降低代碼質量
  • 添加新功能或擴展現有選擇器會導致代碼的其他部分出現錯誤和意外副作用(也稱為回歸)。
  • 具有重複代碼塊或 CSS 代碼塊的多個不同 CSS 選擇器可以分離成一個新的選擇器並通過變化進行擴展。
  • 來自已刪除功能的剩餘、未使用的代碼塊。 開發團隊已經不知道使用了哪些 CSS 代碼,哪些可以安全刪除。
  • 文件結構、CSS 類命名、CSS 整體質量等方面的不一致
  • “特殊性地獄”,通過覆蓋而不是現有的 CSS 代碼庫來添加新功能。
  • 撤消高特異性選擇器“重置”低特異性選擇器樣式的 CSS 。 開發人員正在編寫更多代碼以減少樣式。 這會導致代碼冗餘和大量浪費。
跨多個選擇器(沒有媒體查詢或偽類)有很多劃掉的樣式(在瀏覽器樣式檢查器中)可能是由於結構不良的 CSS 導致的撤消 CSS 的指示。 這些 CSS 類被少數其他沒有媒體查詢和偽類的類覆蓋,導致更多的代碼來實現更少的樣式。 (大預覽)

在最壞的情況下,所有上述問題結合起來可能會導致CSS 文件過大,即使應用了 CSS 縮小。 這個 CSS 通常是渲染阻塞的,所以瀏覽器在完成下載和解析 CSS 文件之前甚至不會渲染網站內容,導致在較慢或不可靠的網絡上的用戶體驗和性能很差。

這些問題不僅會影響最終用戶,還會影響開發團隊和項目利益相關者,使維護和功能開髮變得困難、耗時且成本高昂。 這是在爭論 CSS 重構或重寫時提出的更有用的論點之一。

我最近審核了一個網站,該網站加載了一個 2.2MB 的縮小 CSS 代碼文件。 像這樣異常大的文件可能是 CSS 代碼需要重構甚至從頭開始重寫的潛在指標。 (大預覽)

Netlify 的團隊指出,他們大規模的 CSS 重構項目背後的原因是,隨著項目的複雜性和添加的 UI 組件越來越多,代碼質量和可維護性不斷下降。 他們還注意到,隨著越來越多的人使用 CSS 代碼庫,缺乏內部 CSS 標準和文檔導致代碼質量下降。

“(……)從有組織的 PostCSS 開始逐漸發展成為一個複雜且糾纏不清的全球 CSS 架構,具有許多特殊性和覆蓋性。 正如您所料,它引入的額外技術債務使得在不增加任何回歸的情況下難以保持快速發貨。 此外,隨著貢獻代碼庫的前端開發人員數量也在增長,這種 CSS 架構變得更加難以使用。”
跳躍後更多! 繼續往下看↓

重構還是重寫?

重構允許開發人員在不改變其表現形式或核心功能的情況下,逐步並有策略地改進現有代碼庫。 這些改進通常範圍較小且有限,不會引入破壞性的、廣泛的架構更改或向現有代碼庫添加新的行為、特性或功能。

例如,當前的代碼庫具有卡片組件的兩種變體——第一種是由經驗豐富的開發人員在項目開發早期實現的,第二種是在項目啟動後由經驗不足的開發人員在很短的期限內添加的,所以它具有重複的代碼和具有高特異性的廣泛選擇器。

需要添加第三個卡片變體,它與其他兩個卡片變體共享一些樣式。 因此,為了避免錯誤、重複代碼和復雜的 CSS 類以及 HTML 標記,團隊決定在實現新的變體之前重構卡片組件 CSS。

重寫允許開發人員對代碼庫進行重大更改,並假設當前代碼庫中的大多數(如果不是全部)代碼都將被更改或替換。 重寫允許開發人員從頭開始構建新的代碼庫,解決當前代碼庫中無法修復或修復成本高的核心問題,改進技術堆棧和架構,並為新代碼庫建立新的內部規則和最佳實踐。

例如,客戶正在進行品牌重塑,需要使用新設計和修改內容來更新網站。 由於這是一個開箱即用的站點範圍更改,開發人員決定從頭開始,重寫項目,並藉此機會解決當前 CSS 代碼庫存在但無法通過代碼重構解決的核心問題,更新 CSS 技術堆棧,使用最新的工具和功能,建立新的內部規則和样式的最佳實踐等。

讓我們總結一下每種方法的優缺點。

重構改寫
優點
  • 增量和靈活的過程
  • 使用單個代碼庫
  • 團隊沒有被重構任務鎖定
  • 更容易說服利益相關者和項目負責人進行重構
  • 能解決核心問題; 過時的技術堆棧、命名約定、架構決策、內部規則等。
  • 獨立於當前代碼庫(現有功能和弱點......)
  • 代碼庫可擴展性和可維護性的長期計劃
缺點
  • 取決於當前的代碼庫和核心架構
  • 無法解決核心問題
  • 架構決策、現有的內部規則和最佳實踐、廣泛的問題等。
  • 執行起來可能很複雜,具體取決於項目設置和代碼庫運行狀況
  • 昂貴且耗時
  • 需要在發布前全面實施
  • 在開發新代碼庫的同時維護當前代碼庫
  • 更難說服利益相關者和項目負責人進行完全重寫

何時重構 CSS?

重構是一種推薦的方法,用於在保持當前外觀(設計)的同時逐步改進 CSS 代碼庫。 當沒有任何更高優先級的任務時,團隊成員可以致力於解決這些代碼庫問題。 在大多數情況下,通過逐步改進當前的代碼庫用戶體驗不會直接受到影響,但是,更清潔和更可維護的代碼庫將導致更容易的功能實現和更少的意外錯誤和副作用。

項目利益相關者可能會同意將有限的時間和資源投入到重構中,但他們會期望這些任務能夠快速完成,並期望團隊能夠完成主要任務。

當近期沒有計劃進行大範圍的設計或內容更改時,應定期進行 CSS 重構。 團隊應該在當前 CSS 代碼庫中主動尋找前面提到的弱點,並在沒有更高優先級的任務可用時努力解決它們。

首席前端開發人員或對 CSS 最有經驗的開發人員應該提出問題並創建重構任務,以在代碼庫中強制執行 CSS 代碼質量標準。

何時重寫 CSS?

當 CSS 代碼庫存在無法通過重構解決的核心問題或重構是更昂貴的選擇時,應該重寫完整的 CSS 代碼庫。 從個人經驗來說,當我開始為從另一家公司搬來的客戶工作時,遇到前面提到的 CSS 問題,很明顯重構會很困難,我會首先建議完全重寫,看看有什麼客戶認為。 在大多數情況下,這些客戶對代碼庫的狀態不滿意,並樂於繼續重寫。

完全重寫 CSS 的另一個原因是當網站計劃進行重大更改時——重新命名、重新設計或任何其他影響網站大部分內容的重大更改。 可以安全地假設項目利益相關者意識到這是一項重大投資,並且需要一些時間才能完成重寫。

審計 CSS 代碼庫運行狀況

當開發團隊同意需要重構 CSS 代碼以簡化功能開發工作流程或消除意外的 CSS 副作用和錯誤時,團隊需要將此建議提交給項目利益相關者或項目經理。

提供一些硬數據以及對代碼庫和一般代碼審查的主觀想法是一個好主意。 這也將為團隊提供一個可衡量的目標,他們在進行重構時可以了解這些目標——目標文件大小、選擇器特異性、CSS 代碼複雜性、媒體查詢數量……

在進行 CSS 審核或準備 CSS 重構時,我依靠許多有用的工具中的幾個來獲得有關 CSS 代碼庫的一般概述和有用的統計信息。

我個人的首選工具是 CSS Stats,這是一個免費工具,它提供了對 CSS 代碼庫質量的有用概述,並提供了許多有用的指標,可以幫助開發人員發現一些難以發現的問題。

隨機網站的 CSS Stats 報告的一部分,顯示總 CSS 文件大小、規則數量、選擇器、聲明、屬性等(大預覽)
一個隨機網站的 CSS Stats 報告的一部分,該網站的 CSS 代碼庫很差,具有高特異性選擇器,這使得代碼庫難以維護。 his 是另一個用於跟踪和用於重構目標的有用指標。 (大預覽)

早在 2016 年,trivago 就對其 CSS 代碼庫進行了大規模重構,並使用 CSS Stats 中的指標設定了一些具體的、可衡量的目標,例如降低特異性和減少顏色變化的數量。 在短短三週內,他們設法改善了 CSS 代碼庫的整體健康狀況、減小了 CSS 文件大小、提高了移動設備的渲染性能等。

“像 CSS Stats 這樣的工具可以輕鬆幫助您找出代碼庫中的一致性問題。 指出當每個人對灰色調的外觀有不同的看法時會發生什麼,你最終會得到 50 種灰色陰影。 此外,Specificity Graph 可以很好地整體指示 CSS 基礎的健康狀況。”

至於 CLI 工具,Wallace 是一個方便的工具,它提供了一些基本但有用的 CSS 統計信息和概述,可用於識別與文件大小、規則和選擇器數量、選擇器類型和復雜性等相關的問題。

我的個人網站的華萊士 CLI 報告示例(大預覽)

Wallace 還在 Project Wallace 網站上提供了一個免費的分析工具,它在後端使用了一個看似更高級的 Wallace 版本,以提供一些有用的數據可視化和一些在 Wallace CLI 中不可用的指標。

隨機網站的 Project Wallace 分析器工具示例的一部分。 注意從這幾個統計數據中可以得出多少結論——太多的規則和選擇器、太大的文件大小、太多重複的顏色和字體聲明,等等。(大預覽)

Project Wallace 還為CSS 代碼庫分析提供了完整的付費解決方案。 它具有更多有用的功能和指標,可以幫助開發人員捕捉一些難以發現的問題,並在每次提交的基礎上跟踪 CSS 統計數據的變化。 儘管付費計劃包含更多功能,但免費計劃和基本的 CSS 分析器工具足以審核 CSS 代碼庫質量並獲得總體概覽以製定重構計劃。

編寫高質量的 CSS

我們已經看到 CSS 代碼庫的簡單性和靈活性如何導致代碼質量、性能和視覺錯誤方面的許多問題。 沒有靈丹妙藥的自動工具可以確保我們以最好的方式編寫 CSS 並避免所有可能的架構陷阱。

確保我們編寫高質量 CSS 代碼的最佳工具是紀律、對細節的關注以及通用的 CSS 知識和技能。 開發人員需要不斷地了解大局,並了解他們的 CSS 在大局中扮演的角色。

例如,通過過度指定選擇器,單個開發人員可能會嚴重限制可用性,導致其他開發人員必須複製代碼才能將其用於具有不同標記的其他類似組件。 當開發人員缺乏理解並且沒有利用 CSS 背後的底層機制(級聯、繼承、瀏覽器性能和選擇器特異性)時,通常會出現這些問題。 這些早期決定可能會在未來產生重大影響,因此 CSS 代碼庫的健康和可維護性取決於開發人員的知識、技能和對 CSS 基礎知識的理解。

自動化工具不了解大局或選擇器的使用方式,因此除了強制執行一些基本的、可預測的和嚴格的規則外,它們無法做出這些關鍵的架構決策。

從個人經驗來看,我發現以下內容幫助我顯著改善了我使用 CSS 的方式:

  • 學習架構模式。
    CSS 指南為基於通用編程模式和架構原則編寫高質量 CSS 提供了豐富的知識庫和最佳實踐。
  • 練習和改進。
    從事個人項目或應對來自前端導師的挑戰,以提高您的技能。 從簡單的項目(單個組件或部分)開始,專注於編寫最好的 CSS,嘗試各種方法,應用各種架構模式,逐步改進代碼,並學習如何高效地編寫高質量的 CSS。
  • 從錯誤中學習。
    相信我,當你剛開始的時候,你會寫一些質量很差的 CSS。 你需要嘗試幾次才能把它弄好。 花點時間想想哪裡出了問題,分析弱點,想想你可以做些什麼不同的事情以及如何做,並儘量避免將來犯同樣的錯誤。

在團隊甚至整個公司內建立規則和內部 CSS 標準也很重要。 明確定義的公司範圍的標準、代碼風格和原則可以產生許多好處,例如:

  • 統一且一致的代碼風格和質量
  • 更容易理解,強大的代碼庫
  • 簡化項目入職
  • 任何團隊成員都可以進行標準化的代碼審查,而不僅僅是首席前端開發人員或更有經驗的開發人員

Kirby Yardley 致力於重構聖丹斯學院的設計系統和 CSS,並指出了建立內部規則和最佳實踐的重要性。

“如果沒有適當的規則和策略,CSS 是一種容易被濫用的語言。 開發人員通常會編寫特定於一個組件的樣式,而不會批判性地考慮如何在其他元素中重用該代碼(……)在對我們想要如何構建 CSS 進行大量研究和考慮之後,我們決定使用一種稱為 ITCSS 的方法。 “

回到前面 trivago 團隊的示例,建立內部規則和指南被證明是他們重構過程的重要一步。

“我們引入了一個模式庫,開始在我們的工作流程中使用原子設計,創建了新的編碼指南,並採用了 BEM 和 ITCSS 等幾種方法,以支持我們大規模維護和開發我們的 CSS/UI。”

並非所有規則和標準都需要手動檢查和執行。 像 Stylelint 這樣的 CSS linting 工具提供了一些有用的規則,可以幫助您檢查錯誤並執行內部標準和常見的 CSS 最佳實踐,例如不允許空的 CSS 代碼塊和註釋、不允許重複的選擇器、限制單位、設置選擇器的最大特異性和嵌套深度、建立選擇器名稱模式等

結論

在決定提出細粒度的代碼庫重構或完整的 CSS 重寫之前,我們需要了解當前代碼庫的問題,以便我們可以在未來避免這些問題,並為流程提供可衡量的數據。 CSS 代碼庫可能包含許多複雜的高特異性選擇器,這些選擇器在添加新功能時會導致意外的副作用和錯誤,可能代碼庫受到大量重複代碼塊的影響,這些代碼塊可以移動到單獨的實用程序類中,或者可能是混合各種媒體查詢正在引起一些意想不到的衝突。

CSS Stats 和 Wallace 等有用的工具可以提供 CSS 代碼庫的一般高級概述,並詳細了解代碼庫的狀態和健康狀況。 這些工具還提供可測量的統計數據,可用於設定重構過程的目標並跟踪重構進度。

在確定重構目標和範圍後,重要的是為 CSS 代碼庫設置內部準則和最佳實踐——命名約定、架構原則、文件和文件夾結構等。這確保了代碼的一致性,在項目中建立了可以記錄的核心基礎並可用於入職培訓和 CSS 代碼審查。 使用 Stylelint 之類的 linting 工具可以幫助強制執行一些常見的 CSS 最佳實踐,以部分自動化代碼審查過程。

在這個由三部分組成的系列的下一篇文章中,我們將深入探討一種防彈的 CSS 重構策略,它確保當前代碼庫和重構代碼庫之間的無縫轉換。

部分:CSS 重構

  • 第 1 部分: CSS 重構:簡介
  • 第 2 部分:CSS 策略、回歸測試和維護
  • 第 3 部分:優化大小和性能
  • 訂閱我們的電子郵件通訊,不要錯過下一個。

參考

  • “使用 ITCSS 管理 CSS 項目”,Harry Roberts
  • “Trivago 的大規模 CSS 重構”,Christoph Reinartz
  • “Sundance.org 設計系統和 CSS 重構”,Kirby Yardley
  • “從語義 CSS 到 Tailwind:重構 Netlify UI 代碼庫”,Charlie Gerard 和 Leslie Cohn-Wein
  • “CSS 審計工具”,Iris Lješnjanin