问题
我使用的依赖:
"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');
启动服务,就没有报错了。