場景
一個大體量的項目栅屏,會用到 基礎(chǔ)元組件樣式啸箫,公共樣式耸彪,已經(jīng)模塊樣式等,這些樣式在經(jīng)過webpack編譯后忘苛,會直接呈現(xiàn)在頁面上(如下圖一所示)蝉娜,造成頁面感官凌亂,查閱樣式多次css,style復(fù)寫扎唾,造成樣式浪費召川,增加問題排查難度,于是胸遇,一個共有的css需求便 應(yīng)運而生荧呐;
webpack 對css的一系列插件
webpack 作為資源整合的打包工具, 會從一個入口出發(fā)纸镊,根據(jù) 配合解析的各種loader的一系列配置倍阐,如 less-loader, postcss-loader,css-loader,style-loader 之后,再配合插件逗威,與出口進(jìn)行輸出峰搪;
// webpack.less.js 標(biāo)準(zhǔn)的common.js 寫法
// webpack4+
const OptimizeCssAssetsPlugin = require('optimize-css-assets-webpack-plugin'); // 壓縮工具
const MiniCssExtractPlugin = require('mini-css-extract-plugin'); // css解析壓縮工具
const { CleanWebpackPlugin } = require('clean-webpack-plugin'); // webpack 打包清除
// path獲取
const path = require('path');
// 頂級
const resolveTop = function (dir) {
return path.join(__dirname, '../../..', dir);
};
// css文件存放的目錄
const cssPath = resolveLoc('./public/theme');
// 參數(shù)動態(tài)打包 (多文件打包)
var arguments = process.argv;
const entryObj = {};
const setting = arguments[4];
// console.log("arguments ", arguments);
if (!setting) {
entryObj['theme'] = resolveTop(`./assets/less/theme.less`);
} else {
try {
const list = (setting.split('=')[1]).split(',');
console.log(list);
list.forEach(theme => {
entryObj[theme] = resolveTop(`./assets/less/theme/${theme}.less`)
});
} catch (error) {
throw error;
}
}
const cssConfig = {
mode: 'production',
// 單入口
// entry: {
// theme: resolveTop('./assets/less/theme.less')
// },
entry: entryObj,
resolve: {
alias: {
'@': resolveLoc('./src'),
}
},
optimization: {
minimizer: [
new OptimizeCssAssetsPlugin({}),
],
},
module: {
rules: [
{
test: /\.less$/,
use: [
MiniCssExtractPlugin.loader,
// 'style-loader',
'css-loader',
'postcss-loader',
'less-loader'
],
},
{
test: /\.(jpg|png)$/,
use: [
// 'file-loader',
'url-loader'
],
},
],
},
// css輸出目錄
output: {
path: cssPath
},
plugins: [
new MiniCssExtractPlugin({
filename: `[name].css` // 同名輸出css
}),
new CleanWebpackPlugin()
]
};
module.exports = cssConfig;
命令行使用
// 根據(jù)webpack 特性直接調(diào)用打包
webpack --config webpack.less.js
// 多文件打包 theme1,theme2 可根據(jù)內(nèi)容文件名自定義,輸出與輸入同名
webpack --config webpack.less.js --cumstom=theme1,theme2
引入css
直接引入對應(yīng)的css凯旭,如圖二
多主題引入
// 使用的是vue罢艾,但是本身代碼和vue無關(guān)
// 代碼使用link獲取與style 直接加載兩種方式,各有利弊尽纽,請適量取用
// 換膚
async _changeThemeFun(type) {
// 不存在則渲染 + 加載
// 存在則清除后渲染 + 加載
const theme = document.querySelector('#theme-link');
console.log('theme', theme);
// css link
// this.loadCSS(`/theme/theme${type}.css`);
// style
// axios.get(`/theme/theme${type}.css`).then(res => {
// const cssText = res.data || '';
// this.loadStyle(cssText);
// })
// 請求優(yōu)化
const cssText = await this.getCssTextFun(type);
this.loadStyle(cssText);
},
async getCssTextFun(type) {
if (!this.theme[type]) {
return axios.get(`/theme/theme${type}.css`).then(res => {
const cssText = res.data || '';
this.theme[type] = cssText;
return Promise.resolve(this.theme[type]);
});
} else {
return Promise.resolve(this.theme[type]);
}
},
loadStyle(cssText) {
const STYLE_ID = 'style-css';
const target = document.getElementById(STYLE_ID);
const setCssTxt = (style, cssText) => {
try {
// firefox咐蚯、safari、chrome和Opera
// style.clear();
console.log('style', style);
// style.innerText = '';
// style.appendChild(document.createTextNode(cssText));
style.innerText = cssText;
} catch (ex) {
// IE早期的瀏覽器 ,需要使用style元素的stylesheet屬性的cssText屬性
style.styleSheet.cssText = cssText;
}
};
if (target) {
setCssTxt(target, cssText);
return;
}
const style = document.createElement('style');
style.setAttribute('id', STYLE_ID);
setCssTxt(style, cssText);
document.head.appendChild(style);
},
loadCSS(url) {
const LINK_ID = 'url-link';
// 存在
const target = document.getElementById(LINK_ID);
if (target) {
target.setAttribute('href', url);
return;
}
// 不存在
const element = document.createElement('link');
element.setAttribute('rel', 'stylesheet');
element.setAttribute('type', 'text/css');
element.setAttribute('id', LINK_ID);
element.setAttribute('href', url);
document.head.appendChild(element);
// element.addEventListener('load', (a, b, c) => {
// debugger;
// console.log('a,b,c', a,b,c);
// }, false);
},