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