在一个项目中可能需要同时依赖 antd的两个版本,
npm 6.9.0 添加了 package aliases 功能可以用来解决这个问题
antd多个版本共存的好处,渐进式升级,减少技术风险,实现思路

  1. package.json npm 别名安装antd4,{"antd4": "npm:antd@^4.24.5"}
    1. 别名以 npm: 开头
    2. npm install antd5@npm:antd@^5.0.3
    3. 安装成功后,会显示 antd@5.0.4 (as antd5)
  2. dva修改 webpackrc.js 配置;umijs 修改config.ts
    1. 新增lessLoaderOptions,配置less插件,处理antd4内样式内@antd-prefix
  3. 根组件,ConfigProvider统一修改前缀为antd5

npm alias 自定义安装包别名
https://github.com/jht6/blogs/issues/63
https://github.com/npm/rfcs/blob/main/implemented/0001-package-aliases.md

dva .webpackrc.js配置参考
https://www.jianshu.com/p/c7b3b9c98d04
https://juejin.cn/post/7088140437004746782

package.json

同时安装同一个包的多个版本
antd3x 正常安装,yarn add antd@3.26.19
antd4x 别名安装,yarn add antd4@npm:antd@^4.23.6
antd5x 别名安装,yarn add antd5@npm:antd@^5.0.3
yarn add babel-plugin-import --dev
安装成功后,提示 +antd@4.24.5 (as antd4)

  1. {
  2. "dependencies": {
  3. "antd": "^3.26.20",
  4. "antd4": "npm:antd@^4.24.5",
  5. "antd5": "npm:antd@^5.0.3",
  6. },
  7. "devDependencies": {
  8. "babel-plugin-import": "^1.13.5",
  9. }
  10. }
  11. // 使用不同版本的 antd
  12. import{ Button as ButtonV3 } from 'antd'
  13. import{ Button, Space, Segmented, Cascader } from 'antd5'

antd多版本共存问题

  1. index.css样式冲突
    1. 默认用 cdn引入 antd/index.css 是 antdx3x版本
    2. cdn引入 antd4x的 index.css,不要引入 antd3x,css自己维护样式错乱的组件
    3. antd4的样式需要按需加载
    4. 优化点,自己维护 antd4x的 index.css,修改 prefixCls=antd4后,单独打包构建,然后cdn引入
  2. antd 多版本共存的缺点:造成打包后的 index.js 尺寸增大
  3. antd3x样式,ant-xxx
    1. antd4x样式,antd4-xxx

ConfigProvider

index.js 入口文件,修改 ConfigProvider
ConfigProvider设置prefixCls,修改 antd.css的 ant- 前缀

  1. import { ConfigProvider } from 'antd';
  2. import { ConfigProvider as ConfigProviderV4 } from 'antd4';
  3. import zhCN from 'antd/lib/locale/zh_CN'
  4. import zhCNV4 from 'antd4/lib/locale/zh_CN'
  5. export function routerConfig(props) {
  6. return (
  7. <ConfigProvider locale={zhCN}>
  8. <ConfigProviderV4 locale={zhCNV4} prefixCls="antd4">
  9. {props.children}
  10. </ConfigProviderV4>
  11. </ConfigProvider>
  12. )
  13. }

prefixCls

antd 的组件都有一个 prefixCls 叫 ant-xxx,比如 按钮 组件是 ant-btn。
当多版本 antd 混合的时候,为了解决样式冲突,一般我们会改这个 prefixCls叫一个其他名字然后重新编译一份对应的 css 文件。
但是问题来了,对于静态方法,其实你并没有设置它的 prefixCls,
所以 antd 里又提供了一个静态方法用于设置静态方法的 prefixCls。好吧,这的确有点绕,代码却很简单:

  1. ConfigProvider.config({
  2. prefixCls: xxxx,
  3. });
  4. // 没有 context,那么我们如果要在不同场景下去做不同的 context 该如何处理呢
  5. Notification.open({
  6. prefixCls: xxx,
  7. message: 'Hello World',
  8. });
  9. Notification.open({
  10. getContainer: () => xxx,
  11. message: 'Hello World',
  12. });

.webpackrc.js

  • env 字段是针对特定环境进行配置,HMR 只在开发环境下使用,所以将配置添加到 development 字段即可
  • extraBabelPlugins antd 按需引入 ```json const theme = require(‘@ant-design/aliyun-theme’); const modifyVarsPlugin = require(‘./modifyVarsPlugin’)

module.exports = { “extraBabelPlugins”: [ [ “import”, // antd4 按需引入 { “libraryName”: “antd4”, “libraryDirectory”: “es”, “style”: true }, “antd4” ] ], “env”: { “development”: { “extraBabelPlugins”: [ “babel-plugin-dva-hmr”, // HMR 模块热替换 //“dva-hmr” ] } }, // theme, 删除,移动到下面 lessLoaderOptions: { javascriptEnabled: true, modifyVars: { // 重要的设置,修改 css前缀 “@ant-prefix”: “antd4”, …theme, }, // antd4文件需要经过 loader 处理,node_modules/antd/*.less // include: [/node_modules[\|\/]antd4/], sourceMap: false, plugins: [ modifyVarsPlugin( {‘ant-prefix’: ‘antd4’}, { pathReg: /antd@4/i } ) ] }, }

  1. midifyVars 参考 [https://github.com/ant-design/ant-design/issues/14272#issuecomment-453359894](https://github.com/ant-design/ant-design/issues/14272#issuecomment-453359894)<br />less-load [https://webpack.js.org/loaders/less-loader](https://webpack.js.org/loaders/less-loader)<br />用别名同时安装 antd3和 antd4 两个版本 [https://blog.csdn.net/web220507/article/details/124864455](https://blog.csdn.net/web220507/article/details/124864455)<br />webpack配置参考 [https://www.kancloud.cn/yanli/notebook/1163898](https://www.kancloud.cn/yanli/notebook/1163898)
  2. <a name="NEs9S"></a>
  3. ### modifyVarsPlugins
  4. ```javascript
  5. module.exports = (vars, options) => {
  6. const patterns = Object.entries(vars)
  7. .map(item => {
  8. const [key, val] = item;
  9. return { key, val, reg: new RegExp(`(@${key}):[^;]*;`, 'ig') }
  10. });
  11. return {
  12. install(less, pluginManager) {
  13. pluginManager.addPreProcessor({
  14. process(str, {fileInfo}) {
  15. let result = str;
  16. if (result && options.pathReg.test(fileInfo.filename)) {
  17. patterns.forEach(it => {
  18. result = result.replace(it.reg, `$1: ${it.val};`);
  19. });
  20. return result;
  21. }
  22. return result;
  23. },
  24. });
  25. }
  26. }
  27. }

dva2.4.1 升级 antd5报错

antd 3x,升级到 antd4x,通过 npm别名方式,可以兼容升级;
antd3x,升级到 antd5x,报错,主要是编译 cssinjs的错误,编译无法通过。

  • 升级 antd5,推荐使用 umi4
  • 如果是 antd3x,推荐升级到 antd4x

image.png
image.png
image.png