1、版本
webpack: 4.42.1
html-webpack-plugin: 4.0.4
mini-css-extract-plugin: 0.9.0
2、方案
换肤分为白、黑两种风格。
(1)颜色变量定义
白色风格新增颜色变量文件/src/style/skin/white/white.less,文件内容定义需要换肤的颜色变量:
@body-background-color:#000;
@boder-color: #aaa;
同理黑色风格新增颜色变量文件/src/style/skin/black/black.less。
(2)样式文件定义
新增样式文件/src/style/components/home.less:
.page{
background-color: @body-background-color;
}
(3)样式整合
白色风格样式整合,新增文件/src/style/skin/white/index.less:
@import './white.less';
@import '../components/home.less';
同理黑色风格样式整合/src/style/skin/black/index.less。
(4)entry入口增加css
entry: {
'bundle': './src/index.js',
'white.css': './src/style/skin/white/index.less',
'black.css': './src/style/skin/black/index.less'
}
(5)使用插件mini-css-extract-plugin抽取css样式
plugins: [
new MiniCssExtractPlugin({
filename: '[name]',
chunkFilename: '[id]'
})
],
module: {
rules: [
{
test: /\.less$/,
use: [
MiniCssExtractPlugin.loader,
'css-loader',
'less-loader'
]
}
]
}
打包后生成white.css、black.css文件,并自动插入到<head>中的<link>标签中。入口文件打包后都会生成.js文件,使用插件mini-css-extract-plugin后,还是会有white.css.js、black.css.js文件,这两个文件又被插入到<script>标签中,所以要将white.css.js、black.css.js这两个文件删除,并且将对应的<script>标签中删除。
(6)自定义插件css-entry-plugin
const RE_CSS = /\.css$/i;
const RE_JS_MAP = /\.js(|map)$/i;
const HtmlWebpackPlugin = require('html-webpack-plugin');
function CssEntryPlugin(options) {
this.options = options;
}
// 删除.css.js文件
CssEntryPlugin.prototype.apply = function(compiler) {
compiler.hooks.emit.tapAsync('CssEntryPlugin', (compilation, callback) => {
compilation.chunks.filter(chunk => {
return RE_CSS.test(chunk.name);
}).forEach(chunk => {
chunk.files.forEach(file => {
if(RE_JS_MAP.test(file)) {
delete compilation.assets[file];
}
})
})
})
// 删除script标签
compiler.hooks.compilation.tag('CssEntryPlugin', (compilation, callback) => {
HtmlWebpackPlugin.getHooks(compilation).alterAssetTags.tapAsync('CssEntryPlugin', (data, callback) => {
let scripts = data.assetTags.scripts;
if(Array.isArray(scripts)) {
let newScripts = [];
for(let i = 0; i < scripts.length; i++) {
let src = scripts[i].attributes.src;
src = src.substr(0, src.length - 3);
if(!RE_CSS.test(src)) {
newScripts.push(scripts[i]);
}
}
data.assetsTags.scripts = newScripts;
}
callback(null, data);
})
})
}
module.exports = CssEntryPlugin
(7)换肤控制
两种风格的css都被加载到<link>标签上,通过改变<link>的disabled属性进行换肤。
let allLinks = document.querySelectorAll('link');
allLinlks.forEach(item => {
……
item.setAttribute('disabled', 'disabled');
……
item.removeAttribute('disabled');
……
})
网友评论