[开发随笔] 多 ant-design 版本如何在一个项目共存

646 阅读3分钟

最近接到了一个需求,在 大数据场景下 ,实现一个 表格 并保证浏览器不崩,解法有很多,比如牺牲灵活性采用 canvas 画,或者是为了灵活针对 dom虚拟列表虚拟滚动 这两板斧去改造表格。 不过这些不是本文的重点,因为 开发 这个组件和相关的伴生业务时间只有不到一周的时间,如果从零开始画一个表格,那就更不可能了。

upload_zs4bo1p1lkha82ttujdmvbyibvu1a77p.jpg

在社区摸索了一阵后发现 ant-design 在 5.0 版本中实现了 虚拟表格的功能,文中最后一句话感动了我: upload_1swbrnlyxn1em2tbjxwo21hi9v04d90i.png 既然都这么说了,再不使用就对不起这些 巨人 了。 组件是敲定了,下一步就是怎么把 Table 组件放进去了。

前置背景

upload_9l5ervfczfrp2buyakrg4iur5upnhodg.png

如图所示,这是笔者在项目中使用到的工程结构,项目通过 pnpm 进行管理。apps 目录下是业务模块,libs 目录下便是一些公共的组件/方法库,其中的 antdantd-pro 是前端组基于 antd v4 源码的基础上魔改的一个版本,而且因为各种各样问题,也没办法直接升级到 antd v5 ,业务代码能消费的组件直接来源于此 。那么问题来了:如何在不改动项目已有 antd@4.0 组件依赖的情况下,接入 antd@5.0 的 table 。 针对上述问题,笔者进行了如下几个方案的尝试:

方案一:

升级 rc-table 的版本为最新(截止发文是 7.47.1

但没成功🤡,看了一眼 github,在 4.x-stable 中 table 的依赖也没有对应的修改 upload_5sglkvaqcotzkbfwersou88n7lbf50y1.png

方案二

libs 目录下再建一个依赖 antd@5 的组件库,只对外暴露 Table 组件

相关组件代码如下:

import type { TableProps} from "antd";
import { ConfigProvider, Table, version } from "antd"

export default (props: TableProps) => {
    console.log("version", version);
    
    return <ConfigProvider>
        <Table {...props}/>
    </ConfigProvider>

}

在执行这个方案中,首先采用的是:业务代码直接 源码级 引入相关组件,结果很明显,业务代码打包出来的 Table 组件依然是采用 antd@4 的版本。 于是只能走 先编译,后引入 的方案,直接梭哈 vite。

// vite.config.ts
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
import { resolve } from 'path'

export default defineConfig({
  plugins: [ react()],
  build: {
    lib: {
      entry: resolve(__dirname, 'src/components/table.tsx'),
      name: 'siroi-table',
      fileName: 'index',
      formats: ['es'],
    },

    rollupOptions: {
      external: ['react', 'react-dom' ],
    },
  },
})

按照上述配置文件 build 之后,文件大小约为 900kb ,还是比较大的,有空再看看怎么优化。

业务代码引入打包好的组件后,在 css in js 的加持下,也没有出现 v4 、v5 样式冲突的问题 upload_jj4t3lefalmezk7hwqvh65a5un2dijtu.png

示例如下:

import { useEffect, useState } from 'react';
import HocTable from 'siroi-table';
import { Button } from 'antd';

function createData(num: number = 50) {
  return Array.from({ length: num }, () => ({
    key: Math.random(),
    name: `Name ${Math.floor(Math.random() * 10)}`,
    age: Math.ceil(Math.random() * 10),
  }));
}

export default function Home() {
  const [dataSource, setDataSource] = useState(createData(1000));
  return (
    <div>
      <Button>test</Button>
      <HocTable
        dataSource={dataSource}
        columns={[
          {
            title: '姓名',
            dataIndex: 'name',
          },
          {
            title: '年龄',
            dataIndex: 'age',
          },
        ]}
        pagination={false}
        scroll={{ x: 2000, y: 400 }}
        virtual={true}
        prefixCls="siroi"
        onScroll={(e) => {
          const {scrollTop, scrollTopMax} = e.target as unknown as{scrollTop: number, scrollTopMax: number};
          if(scrollTop === scrollTopMax) {
            console.log('到底了');
            setDataSource([...dataSource, ...createData(50)]);
          }
        }}
      />
    </div>
  );
}

upload_xtaz7r3t5rl1i8qj6hznjcwcw77e2l01.gif

😃使用体验超预期,上线功能后再分析一波源码,手写优化下🤡

总结(如图)

upload_aetect31048vm6yy1ycumsliyajeyiru.png