React 老项目实现 antd3 与 antd4 共存
背景
有一个应用比较古老,用的是antd3,最近一个需求中会用到一个组件TimeRangePicker,但是该组件存在于antd4中,在不升级的情况下无法使用,升级又会导致更多问题,需求的TimeRangePicker自己又不想重新开发,于是想着让antd3与antd4共存于项目中,今后的迭代也逐步替换成antd4。
如何实现共存?
思路比较简单:
别名安装antd4,"antd4": "npm:antd@^conch"
修改config.ts配置,新增lessLoaderOptions,配置less插件,处理antd4内样式内@antd-prefix
ConfigProvider统一修改前缀为antd4
package.json
{
"dependencies":
{
"antd4": "npm:antd@^conch"
}
}
config.ts
export default {
extraBabelPlugins: [
[
'import',
{
libraryName: 'antd4',
libraryDirectory: 'es',
style: true,
},
'antd4',
],
],
lessLoaderOptions: {
plugins: [
lessModifyVarsPlugin(
{
'ant-prefix': 'antd4',
},
{
pathReg: /antd@4/i,
},
),
],
},
};
/**
* @see https://webpack.js.org/loaders/less-loader/
* @returns
*/
function lessModifyVarsPlugin(
vars: Record<string, string>,
pluginOpts: {
pathReg: RegExp;
},
) {
const patterns = Object.entries(vars).map(([key, val]) => ({
key,
val,
reg: new RegExp(`(@${key}):[^;]*;`, 'ig'),
}));
return {
install(less: any, pluginManager: any) {
pluginManager.addPreProcessor({
process(str: string, opts: any) {
const { fileInfo } = opts;
let result = str;
if (pluginOpts.pathReg.test(fileInfo.filename) && result) {
patterns.forEach((item) => {
result = result.replace(item.reg, `$1: ${item.val};`);
});
return result;
}
return result;
},
});
},
};
}
app.ts(x)
import { ConfigProvider as ConfigProviderV4 } from 'antd4';
import { ConfigProvider as ConfigProviderV3 } from 'antd';
import zhCNV4 from 'antd4/es/locale/zh_CN';
import zhCNV3 from 'antd/es/locale/zh_CN';
export function rootContainer(container: any) {
return (
<ConfigProviderV3 locale={zhCNV3}>
<ConfigProviderV4 locale={zhCNV4} prefixCls="antd4">
{container}
</ConfigProviderV4>
</ConfigProviderV3>
);
}