问题
我使用的依赖:
"antd-theme-webpack-plugin": "^1.3.9"
在 vue.config.js
里配置了
const path = require("path");
const AntDesignThemePlugin = require('antd-theme-webpack-plugin');
const options = {
antDir: path.join(__dirname, './node_modules/ant-design-vue'),
stylesDir: path.join(__dirname, './src'),
varFile: path.join(__dirname, './src/assets/styles/theme/variables.less'),
themeVariables: ['@primary-color'],
generateOnce: false
}
const themePlugin = new AntDesignThemePlugin(options);
module.exports = {
css: {
loaderOptions: {
less: {
modifyVars: {
'primary-color': '#1DA57A',
},
javascriptEnabled: true
},
}
},
configureWebpack: {
plugins: [ themePlugin ]
},
}
启动服务就报错了:错误如下
Error LessError: Cannot find module 'antd/lib/style/themes/default.less'
LessError: error evaluating function
darken: color.toHSL is not a function
原因排查分析
既然报错说找不到 antd/lib/style/themes/default.less
文件,我们可以去全局搜索哪里使用了 antd/lib/style/themes/default.less
。
我们可以看到在 ant-design-vue-pro\node_modules\antd-theme-webpack-plugin\node_modules\antd-theme-generator\index.js
文件的 362 行使用了。所以问题就定位到了这个文件,而这个文件所在的包是 antd-theme-generator
,antd-theme-webpack-plugin
里面使用了 antd-theme-generator
。
我们找到https://github.com/mzohaibqc/antd-theme-webpack-plugin/blob/master/package.json,可以看到依赖的是 1.2.8
我们查看其他版本的,比如:1.2.3
,发现代码 fileContent = @import "~antd/lib/style/themes/default.less";\n${fileContent};
注释掉了,所以断定是这个依赖的版本有问题。
解决
其实上面的版本 "antd-theme-generator": "^1.2.3"
,要测试出来符合 antd-theme-webpack-plugin: 1.3.9
,需要我们独自分离这两个包,因为我们安装的是 antd-theme-webpack-plugin: 1.3.9
依赖,而 antd-theme-generator
的版本是由 antd-theme-webpack-plugin
控制的。
我的做法是自己复制一份 antd-theme-webpack-plugin
的代码,当做我们的自定义插件,然后自己主动安装 "antd-theme-generator": "^1.2.3"
即可。
我们新建一个 ant-design-vue-pro\webpack-plugins\antd-theme-webpack-plugin.js
插件:里面的代码直接复制 antd-theme-webpack-plugin
的代码。
// https://github.com/mzohaibqc/antd-theme-webpack-plugin/blob/master/index.js
const { generateTheme } = require("antd-theme-generator");
const webpack = require("webpack");
const { RawSource } = webpack.sources || require("webpack-sources");
const path = require("path");
class AntDesignThemePlugin {
constructor(options) {
const defaultOptions = {
varFile: path.join(__dirname, "../../src/styles/variables.less"),
antDir: path.join(__dirname, "../../node_modules/antd"),
stylesDir: path.join(__dirname, "../../src/styles/antd"),
themeVariables: ["@primary-color"],
indexFileName: "index.html",
generateOnce: false,
lessUrl: "https://cdnjs.cloudflare.com/ajax/libs/less.js/2.7.2/less.min.js",
publicPath: "",
};
this.options = Object.assign(defaultOptions, options);
this.generated = false;
this.version = webpack.version;
}
apply(compiler) {
const pluginName = "AntDesignThemePlugin";
if (this.version.startsWith("5.")) {
compiler.hooks.thisCompilation.tap(pluginName, (compilation) => {
compilation.hooks.processAssets.tapAsync(
{
name: pluginName,
stage:
webpack.Compilation.PROCESS_ASSETS_STAGE_SUMMARIZE,
},
(assets, callback) =>
this.addAssets(compilation, assets, callback)
);
});
} else {
compiler.hooks.emit.tapAsync(pluginName, (compilation, callback) =>
this.addAssets(compilation, compilation.assets, callback)
);
}
}
addAssets(compilation, assets, callback) {
this.generateIndexContent(assets, compilation);
if (this.options.generateOnce && this.colors) {
this.generateColorStylesheet(compilation, this.colors);
return callback();
}
generateTheme(this.options)
.then((css) => {
if (this.options.generateOnce) {
this.colors = css;
}
this.generateColorStylesheet(compilation, css);
callback();
})
.catch((err) => {
callback(err);
});
}
generateIndexContent(assets, compilation) {
if (
this.options.indexFileName &&
this.options.indexFileName in assets
) {
const index = assets[this.options.indexFileName];
let content = index.source();
if (!content.match(/\/color\.less/g)) {
const less = `
<link rel="stylesheet/less" type="text/css" href="${this.options.publicPath}/color.less" />
<script>
window.less = {
async: false,
env: 'production'
};
</script>
<script type="text/javascript" src="${this.options.lessUrl}"></script>
`;
const updatedContent = content
.replace(less, "")
.replace(/<body>/gi, `<body>${less}`);
if (this.version.startsWith("5.")) {
compilation.updateAsset(
this.options.indexFileName,
new RawSource(updatedContent),
{ size: updatedContent.length }
);
return;
}
index.source = () => updatedContent;
index.size = () => updatedContent.length;
}
}
}
generateColorStylesheet(compilation, source) {
if (this.version.startsWith("5.")) {
compilation.emitAsset("color.less", new RawSource(source), {
size: source.length,
});
return;
}
compilation.assets["color.less"] = {
source: () => source,
size: () => source.length,
};
}
}
module.exports = AntDesignThemePlugin;
然后安装依赖,webpack-sources
有就不需要安装了。然后我从 1.2.0
开始往上找,找到了 1.2.3
版本不会报错。
npm install antd-theme-generator@1.2.3 -D
最后修改 vue.config.js
配置里的引用自己定义的插件,其他不需要改动。
const AntDesignThemePlugin = require('./webpack-plugins/antd-theme-webpack-plugin');
启动服务,就没有报错了。