用 AI 做性能分析:一行命令找出拖慢页面的 5 个组件,优化后首屏快了 40%
后台系统用久了越来越卡,尤其是"数据看板"页面,首屏加载 4s+。产品催了三次"能不能快点"。
我用 AI 帮我分析了 bundle 和 render 性能,定位到 5 个问题组件,逐个优化。首屏从 4.2s 降到 2.5s。
分析过程
Step 1:Bundle 分析
bash
# rsbuild 自带 bundle 分析
npm run build:prod -- --analyze
AI 拿到 bundle 分析结果后给出的判断:
matlab
包体积 TOP 5(值得优化的):
────────────────────────────────────────
模块 大小 占比 加载方式
echarts 1.2MB 22% 同步 ❌
@antv/g2 800KB 14% 同步 ❌
moment (遗留) 300KB 5% 同步 ❌
lodash (全量) 70KB 1.2% 同步 ⚠️
wangeditor 500KB 9% 同步 ❌
────────────────────────────────────────
以上合计 2.87MB,占总包 51%
问题:这些库不是每个页面都用,但被打进了主 bundle
方案:按路由动态 import
Step 2:按路由拆分
typescript
// 改造前:同步导入
import DataDashboard from '@/view/dashboard'
import RichEditor from '@/view/marketing/editor'
// 改造后:动态导入
const DataDashboard = lazy(() => import('@/view/dashboard'))
const RichEditor = lazy(() => import('@/view/marketing/editor'))
但光路由拆分不够------echarts 在 5 个不同页面都用了,还是会被打进公共 chunk。
Step 3:AI 建议的深度拆分策略
typescript
// echarts 按需导入(从 500KB 降到 150KB)
// 改造前
import * as echarts from 'echarts'
// 改造后
import * as echarts from 'echarts/core'
import { BarChart, LineChart, PieChart } from 'echarts/charts'
import { GridComponent, TooltipComponent, LegendComponent } from 'echarts/components'
import { CanvasRenderer } from 'echarts/renderers'
echarts.use([BarChart, LineChart, PieChart, GridComponent, TooltipComponent, LegendComponent, CanvasRenderer])
typescript
// lodash 按需导入
// 改造前
import { debounce, throttle, cloneDeep } from 'lodash'
// 改造后
import debounce from 'lodash/debounce'
import throttle from 'lodash/throttle'
import cloneDeep from 'lodash/cloneDeep'
Step 4:渲染性能分析
bundle 优化后首屏 JS 加载快了,但交互还是卡。AI 建议用 React Profiler 分析:
diff
数据看板页面 render 瀑布:
────────────────────────────────────────
组件 render 次数 耗时
DashboardHeader 1 5ms
SalesChart 3 ❌ 120ms
OrderTable 3 ❌ 200ms
RealTimeStats 8 ❌ 40ms×8
FilterPanel 1 10ms
────────────────────────────────────────
问题:
- SalesChart 和 OrderTable 渲染了 3 次(父组件 state 变化导致重渲染)
- RealTimeStats 有定时刷新但没做 memo
Step 5:组件级优化
typescript
// 问题:父组件任何 state 变化都导致图表重渲染
// SalesChart 渲染一次要 120ms(echarts 初始化)
// 解决方案 1:React.memo
const SalesChart = memo(({ data }: { data: SalesData[] }) => {
// 只有 data 变化才重渲染
return <ReactECharts option={getOption(data)} />
})
// 解决方案 2:useMemo 缓存图表配置
const SalesChart = ({ data }: { data: SalesData[] }) => {
const option = useMemo(() => getOption(data), [data])
return <ReactECharts option={option} />
}
// 解决方案 3:RealTimeStats 的定时刷新隔离
const RealTimeStats = memo(() => {
const [stats, setStats] = useState<Stats>()
useEffect(() => {
const timer = setInterval(async () => {
const res = await fetchRealTimeStats()
setStats(res.data)
}, 10_000)
return () => clearInterval(timer)
}, [])
// 自己管理 state,不影响父组件
return <StatCards data={stats} />
})
优化效果汇总
erlang
优化项 优化前 优化后 提升
────────── ────── ────── ────
主 bundle 大小 5.6MB 2.1MB -62%
首屏 JS 加载 2.8s 1.2s -57%
Dashboard 首屏渲染 4.2s 2.5s -40%
图表交互响应 300ms 50ms -83%
路由切换 800ms 200ms -75%
AI 在性能优化中的角色
bash
AI 做得好的:
├── 根据 bundle 分析结果判断哪些包该动态加载
├── 给出 echarts/lodash 按需导入的具体写法
├── 分析组件重渲染原因 + 给出 memo/useMemo 方案
├── 生成优化前后对比的配置代码
└── 提供 rsbuild splitChunks 配置建议
AI 做不到的:
├── 实际运行 Profiler 看数据(需要你手动操作)
├── 判断业务上这个组件能不能 memo(可能有隐式依赖)
├── 衡量"值不值得优化"(需要你定优先级)
└── 线上真实用户的性能数据收集
Rsbuild 分包配置(AI 建议的最终版)
typescript
performance: {
chunkSplit: {
strategy: 'custom',
splitChunks: {
cacheGroups: {
// antd 单独打包(几乎所有页面都用)
antd: {
test: /[\\/]node_modules[\\/](antd|@ant-design)[\\/]/,
name: 'antd',
chunks: 'all',
priority: 30,
},
// echarts 单独打包(按需加载)
echarts: {
test: /[\\/]node_modules[\\/](echarts|zrender)[\\/]/,
name: 'echarts',
chunks: 'async', // 只在用到时才加载
priority: 20,
},
// 其他第三方
vendors: {
test: /[\\/]node_modules[\\/]/,
name: 'vendors',
chunks: 'all',
priority: 10,
},
},
},
},
}
什么时候该做性能优化
arduino
值得优化的信号:
├── 用户反馈"慢"(感知 > 3s 就算慢)
├── bundle 超过 3MB(SPA 的警戒线)
├── 某个页面首屏 > 3s
├── 交互有明显卡顿(输入延迟、滚动卡)
└── Lighthouse 性能分 < 60
不需要过早优化的:
├── 没有用户投诉
├── 内部工具(用户能接受 2-3s)
├── 页面本身就不复杂
└── 团队人力紧张(先做功能)
💬 你们项目的 bundle 有多大?首屏加载时间是多少?有做过性能优化吗?
🔗 完整 Skills 源码已开源 :github.com/sleepyccat/...,欢迎 Star ⭐ 和 PR。