In the recent project, we want to realize a skin changing function. I have thought about it in general and recorded my thoughts
The goal is to package multiple skin files and use whichever one is needed
Package to generate multiple skin files
Because the project is built using WebPack, to generate multiple CSS files, you configure multiple entry files in the entry, and each entry file extracts one CSS file
config.entry={
app: ['./src/app.js'],
defaultTheme: ['./src/theme.default.color.js'],
orangeTheme:['./src/theme.orange.color.js'],
blueTheme:['./src/theme.blue.color.js'],}Copy the code
App. Js
import "./app.styl"// The part of the whole project that remains the same under all skinsCopy the code
Theme. Blue.color. js Blue skin JS file
import "./theme/blue.styl"Copy the code
Blue. Styl Blue skin
@require "./css/skinTheme/var.blue"// Style variable, the overall blue style color value @require"./css/skinTheme/theme.color"// The extracted part of the style that needs to be skinnedCopy the code
As the code shows, several theme JS files simply introduce the corresponding skin style files, so that webpack will generate several useless JS files and a series of skin style files
At this point, you have the skin files you need, but note that WebPack inserts the generated JS and CSS paths into the template HTML, so we’ll see when we open the build and generate 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>Copy the code
Operation index. HTML
The next step is to manipulate the packed index.html, remove the excess JS references, extract the skin path, and then delete the skin references
So you want to change it to something like this
/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>Copy the code
You can write a function that operates on a file
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) /** * Delete all theme CSS, related links saved in 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 ()}}})/delete useless js * * * * / $('script').each((index, item) => {
const src = $(item).attr('src')
for (const val of prefix) {
if(src && src.indexOf(val) ! == -1) {$(item).remove()}}})'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()Copy the code
The last
From here, we run webpack && node cssextract.js, and index.html looks like what we expected above. We need to get a mapping of the skin file and save it in window.cssurls. You can toggle buttons to switch skins or whatever.
It should be noted that the focus of the skinning function is the reconstruction of the style. All the styles that need to be skinning are extracted together and different themes can be set through variables
source