[從 0 開始的 Angular 生活]No.54 在 Angular 中切換預設 or 深色主題

前言

自上一篇文章後,就很少上來發表文章了,一方面是工作到家就有點累了,更別說沒有想到什麼適合寫的主題。剛好前幾天有個 Issue 希望我研究如何在 Angular 中快速的切換預設 / 暗色主題,也就是所謂的開關燈模式囉。

環境建置

探索

稍微了解情況後便立即開始展開網路上的搜尋,初步的整理出了以下兩種方案:

  1. 透過添加 / 移除 className 的方式切換主題
  2. 透過設置 angular.json 使其打包出兩份不同的主題 CSS ,並且將其動態引入

先破梗,兩種方案都有優缺點,端看團隊的情況能接受哪一種方案。最後我們團隊是採用第二種方案,因為這對我們來說,能避開最多可預見的問題。

實作

方案一

透過異動 className 達成切換主題的方式可以參考這篇文章做一些微調即可。

嘗試過後覺得不太適合我們,理由如下:

  1. 兩種主題打包後的單支 CSS 檔案太大了
  2. 由於是在最外層的標籤套上特定的 className 來切換主題,以我們專案來說會出現 CSS 權重問題造成跑版。
    • 而如果要解決這個問題,則需要到作為基底的 lib 內調整 Bootstrap 4 & Angular Material 等相關的 SCSS ,評估後覺得這個不是目前最佳解,暫時跳過。

方案二

做法如下:

  • 建立兩份主題,如: default-theme.scssdark-theme.scss
  • 調整 angular.json
    • 調整 styles 區塊配置
      • 設定 inputbundleNameinject 屬性
        • input - 要載入的 SCSS 路徑
        • bundleName - 獨立打包的檔案名稱
        • inject - 是否自動載入至 index.html
    • 調整 configurationsoutputHashing 配置
      • 將其設定為 bundles ,確保打包後的 CSS 檔案名稱不會被加上 hash
    • 調整 build 內的 options 區塊配置,加入 extractCss 屬性,設置為 true
  • 新增 CSSLoaderService 用來動態引入指定的 CSS
  • 調整 index.html ,使其預設載入 default-theme.scss

範例:GitHub

成果 Gif 圖

結論

透過方案二的做法,能有效的控制 CSS 大小,不會因為兩種主題而使 CSS 檔案膨脹,而這個做法也相當的簡單暴力。

甚至可以繞過很多不好處理的問題,像是 SCSS 內的變數宣告順序、又或者是多了 !default 的 SCSS 變數,方案二並非方案一是將全部 SCSS 都打包再一起成為 CSS ,所以會讓情況單純很多。

當然方案二也不是完全沒有缺點的,像是:

  • 取消掉 hash 後可能需要處理 CSS 被快取住的問題 (待驗證)
  • 如果單個主題 CSS 本身就有點分量,那麼切換時可能會有點延遲,這時需要透過 viewblock 等手段提升使用者體驗。
0%