sourcecss
最近項目中要實現一個換膚的功能,大致想了下,記錄一下思路html
要實現換膚功能,目標就是打包生成多份皮膚文件,須要哪一個就用哪一個node
由於項目是使用webpack構建的,要想生成多份css文件,就要在入口中配置多個入口文件,每一個入口文件會提取出一個css文件webpack
config.entry={ app: ['./src/app.js'], defaultTheme: ['./src/theme.default.color.js'], orangeTheme:['./src/theme.orange.color.js'], blueTheme:['./src/theme.blue.color.js'], }
app.js中git
import "./app.styl" //整個項目的樣式,在各類皮膚下都保持不變的那部分
theme.blue.color.js 藍色皮膚js文件github
import "./theme/blue.styl"
blue.styl 藍色皮膚web
@require "./css/skinTheme/var.blue" //樣式變量,總體爲藍色風格的顏色值 @require "./css/skinTheme/theme.color" //提取出來的須要換膚的那部分樣式
如代碼所示,幾個主題js文件
中只是單純的引入了相應的皮膚樣式文件,這樣,webpack打包後就會生成幾個無用的js文件和一系列皮膚樣式文件app
到這一步,就獲得了須要的皮膚文件,可是須要注意的是,webpack會將生成的js、css路徑插入到模板html中,因此,咱們打開構建後生成index.html會看到函數
<html> <head> <link rel="stylesheet" href="app.xxxx.css"> <link rel="stylesheet" href="defaultTheme.xxxxx.css"> <link rel="stylesheet" href="orangeTheme.xxxxx.css"> <link rel="stylesheet" href="blueTheme.xxxxx.css"> </head> <body> <script src="app.xxxx.js"></script> <script src="defaultTheme.xxxx.js"></script> <script src="orangeTheme.xxxx.js"></script> <script src="blueTheme.xxxx.js"></script> </body> </html>
接下來就須要操做打包後的index.html,將多餘的js引用刪掉,將皮膚路徑提取出來,而後將皮膚引用刪掉ui
也就是要改爲這樣的文件
/build/index.html
<html> <head> <script> window.cssUrls={ "defaultTheme":"/defaultTheme.4bdb738cdc062e7842ce.css", "orangeTheme":"/orangeTheme.4bdb738cdc062e7842ce.css","blueTheme":"/blueTheme.4bdb738cdc062e7842ce.css" } </script> <link rel="stylesheet" href="app.xxxx.css"> </head> <body> <script src="app.xxxx.js"></script> </body> </html>
能夠寫這樣一個操做文件的函數
cssExtract.js
const DISTPATH = 'build/index.html' const cheerio = require('cheerio') const fs = require('fs') const chalk = require('chalk') const prefix = ['defaultTheme', 'orangeTheme', 'blueTheme'] const cssUrls = {} function extractCss() { fs.readFile(DISTPATH, 'utf8', (err, data) => { if (err) { throw err } const $ = cheerio.load(data) /** * 刪除全部主題css,相關連接保存在window.cssUrls中 */ $('link').each((index, item) => { const href = $(item).attr('href') for (const val of prefix) { if (href.indexOf(val) !== -1) { cssUrls[val] = href $(item).remove() } } }) /** * 刪除無用的js */ $('script').each((index, item) => { const src = $(item).attr('src') for (const val of prefix) { if (src && src.indexOf(val) !== -1) { $(item).remove() } } }) //插入行內js $('base').after(`<script>window.cssUrls=${JSON.stringify(cssUrls)}</script>`) fs.writeFile(DISTPATH, $.html(), err => { if (err) { throw err } console.log(chalk.cyan('extract css url complete.\n')) }) }) } extractCss()
到這裏,運行 webpack && node cssExtract.js
,index.html就變成上面指望的那樣,咱們得要了皮膚文件的一個mapping,並保存在window.cssUrls中,接下來,經過切換按鈕的方式切換皮膚仍是什麼其餘的就能夠自由發揮了.
須要說明的是,換膚功能的重點是對樣式的重構,將須要換膚的全部樣式提取到一塊兒,經過變量來設置不一樣的主題