如何利用webpack實現(xiàn)一鍵換膚(CSS變量替換)

最近公司項目中有一個需要更換web端主題的需求,基本實現(xiàn)效果如下:
如何利用webpack實現(xiàn)一鍵換膚

接收到這個需求的時候有三種思路:

  • 打包的時候同時冗余打包多套CSS文件,并在切換主題的時候加載相應(yīng)的樣式文件。
  • 在根組件上加上主題類名,并在切換主題的時候改變類名,然后通過CSS類來覆蓋已有樣式。
  • 利用 antd-theme-webpack-plugin將less文件加載,并在線解析less文件后覆蓋已有CSS
  • 線上解析所有樣式代碼,并根據(jù)新的顏色重新生成樣式,并加入HTML中 下面逐個方案分析:

方案一:打包的時候同時冗余打包多套CSS文件

劣勢相當明顯,第一是打包速度嚴重拖慢,第二是切換主題的時候還需要重新從服務(wù)器上獲取CSS文件,意味著切換個主題需要等上好幾秒之后才能見效。優(yōu)勢的話,估計就是實現(xiàn)起來稍微簡單一點了。但這個很明顯不是我想要的結(jié)果。

方案二:在根組件上加上主題類名

優(yōu)勢在于切換成本比較低,但是劣勢也比較明顯:第一是打包體積嚴重增加(多加一套主題樣式文件幾乎增加一倍),第二是后續(xù)代碼維護困難,需要把所有需要更換主題的樣式文件全部寫進所有主題類里面,工作量太大,而且是個無底洞。

方案三:利用 antd-theme-webpack-plugin

這套方案的可以根據(jù)antd里面的所有l(wèi)ess文件中的變量進行替換,正好我們的項目又是基于Reactantd,簡直完美融合。于是欣然試用,最終試用結(jié)果是:我水土不服了。做個簡單的demo的時候運行很好,沒問題,但是移植到已有項目的時候就出現(xiàn)各種不適應(yīng),首先是版本問題,這個好解決。然后又出現(xiàn)其他報錯,一個一個解決完了之后發(fā)現(xiàn)實際運行起來之后還是水土不服。

另外這種模式還有另外的劣勢,必須額外加載less文件,并且在線上解析所有l(wèi)ess文件,然后應(yīng)用到DOM中,對于我們這個光是樣式文件打包(還是minify之后的)起來都有1M左右的項目來說簡直是災難。

方案四:線上解析所有樣式代碼

這種方案其實是比較討巧的做法,將所有的linkstyle標簽的樣式取出來,然后替換相應(yīng)的變量,再注入到DOM節(jié)點中,完成樣式替換。不需要太多額外的文件引入,是一個比較好的實現(xiàn)思路,唯一的問題就在于前面提到的1M多的樣式文件,考慮到本身項目已經(jīng)比較龐大,在加上這么大的額外開銷還是忍痛拒絕了。

于是主題到了:并非所有的樣式代碼都需要解析的,因為畢竟換膚一般來說只會更換一兩個顏色,而不會更換所有的樣式文件,那么何不在發(fā)布線上之前就將CSS解析好,線上的時候只需要解析這些已經(jīng)處理好的樣式文件即可,實際操作下來之后1M左右的樣式文件只需要處理幾KB的數(shù)據(jù)。在實際線上運行之后發(fā)現(xiàn)也確實比較流暢,也就是文章開頭的GIF的效果了。

這個方案靈感來源于 webpack-theme-color-replacer,該項目通過webpack插件形式將樣式文件解析后將更換主題的代碼注入到每個js頭部,實現(xiàn)思路很漂亮,只是看了代碼之后有幾個問題:

  • 樣式加載到每個js頭部,冗余!
  • 顏色匹配必須對應(yīng)array中的順序,而且不直觀
  • 需要額外再代碼中引入樣式替換的js

綜合起來覺得使用起來比較繁瑣,于是自己動手擼了一個webpack插件:webpack-stylesheet-variable-replacer-plugin,只需要在webpack配置中增加一個plugin,其他的就OK了,支持key--value方式來定義需要替換的變量,還有就是注入文件可控,不會重復注入。下面介紹一下使用方法,簡單三步走:

  • 引入插件
const WebpackVariableReplacer = require('webpack-stylesheet-variable-replacer-plugin');

  • 定義插件配置信息
new WebpackVariableReplacer({
     publicPath: '',
     buildPath: 'static/',
     nextSupport: true,
     specifyEntry: /_app\.js/,
     matchVariables: {
           main: '#209CEE',
         }
     }),

  • 客戶端調(diào)用替換主題的方法:
 window.replaceStyleVariable && window.replaceStyleVariable({main: color});

運行效果還是看文章開頭的GIF,總結(jié)來說,效率高,代碼侵入性低,方便使用。理論上來說,在angular和vue中使用也沒有任何問題。不過本人主要技術(shù)棧還是react,其他沒有測試。 下面解釋一下使用參數(shù):

參數(shù) 默認值 詳細說明
fileName webpack-variable-replacer-[hash].js
publicPath '' 資源訪問路徑
htmlFileName '' 需要注入的HTML文件名
buildPath ‘’ 文件打包后存放的位置前綴
nextSupport false 是否需要支持next.js,如果后端服務(wù)用next.js搭建,此參數(shù)需傳true
injectToEntry false 是否需要將生成后的代碼注入到打包的js中,如果穿了htmlFileName,此參數(shù)可傳false,否則必須為true
excludeEntry null 需要排除的entry文件名,支持傳入正則或者正則字符串
specifyEntry null 需要指定的entry文件名,支持傳入正則或者正則字符串,不傳默認所有
matchVariables {} 需要匹配的字符串,通過key-value模式傳入,例如:{main:'#123456'}

我的主頁:eaTong個人站

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 在現(xiàn)在的前端開發(fā)中,前后端分離、模塊化開發(fā)、版本控制、文件合并與壓縮、mock數(shù)據(jù)等等一些原本后端的思想開始...
    Charlot閱讀 5,690評論 1 32
  • 1. 新建一個文件夾,命名為 webpack-cli , webpack-cli 就是你的項目名,項目名建議使用小...
    魯大師666閱讀 1,671評論 1 3
  • 前提: 安裝webpack、webpack-cli 一、首先先讓出來一個頁面有內(nèi)容 先添加.gitignore,將...
    codingQi閱讀 1,563評論 0 0
  • 本項目基于 入門 Webpack,看這篇就夠了創(chuàng)建。本例程通過從頭構(gòu)建一個基于npm管理的前端項目,一步步的讓讀者...
    尤利西斯U閱讀 3,322評論 0 8
  • 星空百億年,不過幻起滅; 庸人多爭讻,高人只觀天。 時來茶花園,花色一時明; 命數(shù)與人心,交互成一體。
    道聽俗說閱讀 418評論 0 2

友情鏈接更多精彩內(nèi)容