Replace antd theme
没有整啥插件,使用 less variable
覆盖即可
Background
现在大多数中后台开发都是基于第三方UI(如 antd, element-ui),通常业务也会要求自己的主题定制,这就涉及到所谓的 换肤
。
庆幸的是,这些 UI
提供了这样的功能,拿 antd
来说,themes/default.less 包含了其使用的全部颜色变量,业务只需要覆盖即可。
// -------- Colors -----------
@primary-color: @blue-6;
// >>> Warning
@warning-color: @gold-6;
Why
颜色定制的原理,其实是 less
提供了对 less variables
的修改,参考 文档
less.modifyVars({
'@buttonFace': '#5B83AD',
'@buttonText': '#D9EEF2'
});
所以只需要在构建里加一个自动 modifyVars
,注入对应的变量即可
css: {
preprocessorOptions: {
less: {
modifyVars: generateModifyVars(),
javascriptEnabled: true,
},
},
},
function generateModifyVars() {
return {
hack: '; @import (reference) ./src/styles/theme.less'
}
}
这是我在网上找到的大多数版本,看到这几行代码,我有几个疑惑
javascriptEnabled
干啥的- 除了
modifyVars
还有其他参数吗 hack
干啥的@import (reference)
和@import
有什么区别
Q1 javascriptEnabled
开启这个即允许 code injection
,但是
False by default starting in v3.0.0. Enables evaluation of JavaScript inline in .less files. This created a security problem for some developers who didn’t expect user input for style sheets to have executable code.
理论上来说,修改 less variable
不需要这个参数,但是因为我们依赖的是 antd
,这个 UI
定义了一个基于 less
变量的调色板,这里有一堆 js function
,比如
.colorPaletteMixin() {
@functions: ~`(function() {
var getHue = function(hsv, i, isLight) {
};
}
这就导致我们不得不开启这个选项
Q2 modifyVars
还有 globalVars
,区别就是一个是在文件头部,一个在文件最后注入。当然,如果你在文件头部注入,业务恰好有同名变量,也是会被覆盖,这个要注意,所以我们采用 modifyVars
lessc --global-var="color1=red" { globalVars: { color1: 'red' } }
lessc --modify-var="color1=red" { modifyVars: { color1: 'red' } }
除了这两个,我们还可以注入 banner
,看一下源码
parse: function (str, callback, additionalData) {
let globalVars;
let modifyVars;
let preText = '';
globalVars = (additionalData && additionalData.globalVars) ? `${Parser.serializeVars(additionalData.globalVars)}\n` : '';
modifyVars = (additionalData && additionalData.modifyVars) ? `\n${Parser.serializeVars(additionalData.modifyVars)}` : '';
if (globalVars || (additionalData && additionalData.banner)) {
preText = ((additionalData && additionalData.banner) ? additionalData.banner : '') + globalVars;
}
}
Q3 hack
这个其实你可以用任意的名字,不信看 源码实现
Parser.serializeVars = vars => {
let s = '';
for (const name in vars) {
if (Object.hasOwnProperty.call(vars, name)) {
const value = vars[name];
s += `${((name[0] === '@') ? '' : '@') + name}: ${value}${(String(value).slice(-1) === ';') ? '' : ';'}`;
}
}
return s;
};
所以,
{
hack: '; @import (reference) ./src/styles/theme.less;'
}
最终会变成 @hack: ; @import (reference) ./src/styles/theme.less';
Q4 @import (reference)
为啥不是 @import
呢??看下 官方文档 怎么说的?
Imagine that reference marks every at-rule and selector with a reference flag in the imported file, imports as normal, but when the CSS is generated, “reference” selectors (as well as any media queries containing only reference selectors) are not output. reference styles will not show up in your generated CSS unless the reference styles are used as mixins or extended.
这种方式可以按需引入,打包的时候,只会编译业务用到的一些变量、类等。