Ant Design Pro实战:从搭建到优化的完整开发经验分享
优化前:卡得不行
上周接手一个老 Ant Design Pro 项目,打开首页直接卡住 3 秒多,表格页滚动掉帧,切换菜单时明显卡顿。最离谱的是,登录后首屏加载时间飙到 5.2 秒(本地 dev server,没开 sourcemap),用户反馈“点一下等半天”,我本地开发都忍不住想砸键盘。
这项目用了 Ant Design Pro V5,基于 Umi + React + Ant Design,页面不算特别复杂,但 bundle 体积大得离谱——主包 4.8MB,vendors 包 6.1MB。光是 antd 组件就全量引入了,lodash 也整个打进来了,更别说一堆没用的图表库和工具函数。
找到瓶颈了!
先别急着改代码,得知道慢在哪。我干了三件事:
- 用 Chrome DevTools 的 Performance 面板录了一次首页加载,发现 scripting 时间占了 70% 以上,主要是大量模块初始化和 React 渲染
- 跑
npx source-map-explorer build/static/js/*.js,一眼看到 antd、moment、echarts、lodash 占了大头 - 在 Umi 配置里开了
analyze: { analyzerMode: 'server' },启动后自动打开 bundle 分析图,vendors 里 antd 相关模块密密麻麻
结论很明确:**包太大 + 按需加载没配好 + 首屏渲染做了太多事**。
核心优化:砍包 + 懒加载 + 渲染瘦身
折腾了两天,主要动了三块地方,效果立竿见影。
1. 彻底解决 antd 全量引入问题
项目里明明用了 babel-plugin-import,但配置错了。原来写的是:
// .umirc.ts 错误配置
export default {
extraBabelPlugins: [
['import', { libraryName: 'antd', style: true }],
],
}
结果 Umi 内部已经内置了按需加载,再手动加反而冲突。正确做法是:删掉 extraBabelPlugins 里的 import 配置,Umi 默认就支持 antd 按需加载。改完后,antd 相关体积从 2.1MB 降到 400KB 左右。
另外,检查所有组件是否真的按需引入。比如有人写了 import { Button, Table, Modal } from 'antd',这是对的;但如果有 import antd from 'antd' 就完蛋了。全局搜了一遍,修了两处。
2. 路由级懒加载 + 组件级懒加载
Ant Design Pro 默认用 Umi 的动态路由,但有些页面还是同步加载。我把所有非首屏页面都改成懒加载:
// config/routes.ts
export default [
{
path: '/dashboard',
component: './Dashboard',
// 改成
component: () => import('@/pages/Dashboard'),
},
{
path: '/user',
component: () => import('@/pages/User'),
}
]
更狠的是,对页面内部的大组件也做懒加载。比如有个数据看板页,里面嵌了三个大图表,我用 React.lazy + Suspense 包起来:
const ChartA = React.lazy(() => import('./ChartA'));
const ChartB = React.lazy(() => import('./ChartB'));
const Dashboard = () => {
return (
<div>
<Suspense fallback={<Spin />}>
<ChartA />
<ChartB />
</Suspense>
</div>
);
};
这样首屏只加载必要内容,图表等用户滚动到可视区域再加载(配合 IntersectionObserver 更佳,但这里先求快)。
3. 干掉 moment,换成 dayjs
antd 依赖 moment,但 moment 太重(300KB+)。Umi 提供了替换方案,在 .umirc.ts 里加:
export default {
define: {
'process.env.USE_DAYJS': true,
},
chainWebpack(memo) {
memo.plugins.delete('moment');
},
}
同时安装 dayjs 和 antd-dayjs-webpack-plugin:
npm install dayjs antd-dayjs-webpack-plugin
然后在 config/config.ts 里配置:
import AntdDayjsWebpackPlugin from 'antd-dayjs-webpack-plugin';
export default {
chainWebpack(config) {
config.plugin('antd-dayjs').use(AntdDayjsWebpackPlugin);
}
}
搞定后,moment 相关代码彻底消失,减了 300KB+。注意:有些老代码用了 moment 的 API,得手动替换成 dayjs,但工作量不大。
4. 首屏渲染优化:别在 render 里干重活
发现有个列表页,每次渲染都要处理上千条数据,还用了 map + filter + sort 嵌套,直接卡死。优化思路:**计算移到 useEffect 里,结果缓存**。
优化前:
const UserList = ({ users }) => {
const filteredUsers = users
.filter(u => u.active)
.sort((a, b) => a.name.localeCompare(b.name))
.map(u => ({ ...u, displayName: ${u.name} (${u.role}) }));
return <Table dataSource={filteredUsers} />;
};
优化后:
const UserList = ({ users }) => {
const [filteredUsers, setFilteredUsers] = useState([]);
useEffect(() => {
const result = users
.filter(u => u.active)
.sort((a, b) => a.name.localeCompare(b.name))
.map(u => ({ ...u, displayName: ${u.name} (${u.role}) }));
setFilteredUsers(result);
}, [users]);
return <Table dataSource={filteredUsers} />;
};
虽然简单,但实测列表渲染从 1200ms 降到 200ms 以内。如果数据量更大,还可以加 useMemo 缓存,但这里 useEffect 足够了。
其他小优化(带过)
- 删掉不用的依赖:项目里装了
lodash,但只用了debounce和throttle,直接换成原生或 tiny-lodash,省了 70KB - 图片压缩:用 imagemin-webpack-plugin 压缩静态资源,图片体积减半
- 开启 Gzip:Nginx 层配置 gzip,传输体积再减 70%
- 避免在 render 里创建新函数:把
onClick={() => handle(id)}改成useCallback包裹,减少子组件重渲染
性能数据对比
优化前后关键指标(本地 dev server,无 sourcemap,Chrome 无痕模式):
- 首屏加载时间:5.2s → 800ms(下降 85%)
- 主包体积:4.8MB → 1.1MB
- vendors 体积:6.1MB → 1.9MB
- 内存占用:从 400MB+ 降到 200MB 左右
上线后,用户反馈“终于不卡了”,老板也松了口气。其实很多优化都是老生常谈,但 Ant Design Pro 项目容易踩的坑就是:默认配置不够激进,开发者又懒得调,结果包越滚越大。
最后说两句
这次优化后,仍有两个小问题:一是某些低端机上长列表滚动还是轻微掉帧(后续考虑虚拟滚动),二是首屏 API 请求太多(可合并或缓存)。但整体体验已经从“不能用”变成“流畅”,值了。
以上是我个人对 Ant Design Pro 性能优化的实战总结,核心就是:**砍包、懒加载、别在 render 里干重活**。有更优的实现方式欢迎评论区交流,比如你们怎么处理超大表格的?我还在找更好的方案。

暂无评论