一、问题:首屏加载2.5秒,用户等不起
简记往来上线后,我统计了首屏加载时间------平均2.5秒。
2.5秒意味着什么?用户打开小程序,等2.5秒才能看到内容。很多用户会在这个时间点关掉。
微信小程序的性能标准是:首屏加载时间建议控制在1.5秒以内。2.5秒明显超标了。
问题出在哪?我分析了几个关键因素:
- 主包体积过大:所有页面都在主包里,加载时一次性下载全部代码
- 首屏渲染数据过多:首页一次性加载了所有账本和最近的记录
- 图片未优化:部分图标和背景图没有压缩
二、优化一:分包加载
微信小程序的主包大小限制为2MB ,分包后总包可达20MB 。分包加载的核心思想是:主包只放首页和TabBar页面,其他页面按需加载。
简记往来的分包方案:
主包(~800KB):
├── pages/index/ # 首页
├── pages/daily/ # 日常账本(TabBar页面)
├── pages/gift/ # 礼账本(TabBar页面)
├── pages/profile/ # 我的(TabBar页面)
└── components/ # 基础组件
分包1(~400KB):
└── pages/report/ # 报表页面(非TabBar)
分包2(~300KB):
└── pages/settings/ # 设置页面(非TabBar)
分包3(~200KB):
└── pages/help/ # 帮助页面(非TabBar)
json
// app.json 分包配置
{
"pages": [
"pages/index/index",
"pages/daily/daily",
"pages/gift/gift",
"pages/profile/profile"
],
"subpackages": [
{
"root": "pages/report",
"pages": ["report"]
},
{
"root": "pages/settings",
"pages": ["settings"]
},
{
"root": "pages/help",
"pages": ["help"]
}
]
}
分包加载后,首屏只需加载主包(800KB),而不是全部代码(1.7MB)。首屏加载时间从2.5秒降到1.8秒。
某新闻类小程序采用类似方案后,首屏加载时间甚至缩短至1.2秒。
三、优化二:图片懒加载
首屏不需要展示的图片,延迟加载。
简记往来的做法:列表页的缩略图使用 lazy-load 属性,滚动到可视区域时才加载。
html
<image src="{{item.avatar}}" lazy-load="true" mode="aspectFill" />
同时,所有图片统一转为 WebP 格式,体积减少约30%。
效果:首屏加载时间再降0.3秒,降到1.5秒。
四、优化三:setData优化
微信小程序的 setData 是性能瓶颈。频繁调用 setData 会导致页面卡顿。
问题代码:
javascript
// ❌ 多次setData
this.setData({ list: newList })
this.setData({ total: newTotal })
this.setData({ page: newPage })
优化后:
javascript
// ✅ 合并为一次setData
this.setData({
list: newList,
total: newTotal,
page: newPage
})
另一个常见问题是:用 setData 更新与渲染无关的字段,这会触发额外的渲染流程。
javascript
// ❌ 错误:用setData更新内部状态
this.setData({ _cache: someData })
// ✅ 正确:直接用this.data或普通变量
this._cache = someData
微信小程序单次 setData 的数据量建议控制在 64KB 以内。超过这个量,渲染性能会明显下降。
简记往来的首页列表原本一次性加载30条记录,每条记录包含完整信息,数据量约80KB。改为分页加载(每次10条)后,单次setData数据量降到20KB以内。
效果:页面交互流畅度明显提升,首屏加载时间最终稳定在1.2秒。
五、优化四:减少首次渲染数据量
首屏加载时,只加载必要的数据。
javascript
// ❌ 加载全部数据
const allBills = await fetchAllBills()
this.setData({ bills: allBills })
// ✅ 只加载首屏需要的数据
const pageData = {
recentBills: await fetchRecentBills(10), // 只取最近10条
summary: await fetchSummary() // 只取汇总数据
}
this.setData(pageData)
首页不需要展示全部记录,只需要最近10条和统计摘要。用户滚动到底部时,再加载更多。
六、优化效果汇总
| 优化项 | 优化前 | 优化后 | 提升 |
|---|---|---|---|
| 分包加载 | 1.7MB全量加载 | 800KB按需加载 | -53% |
| 图片优化 | 未压缩 | WebP+懒加载 | -30%体积 |
| setData合并 | 多次调用 | 单次合并 | 减少渲染次数 |
| 数据分页 | 30条/次 | 10条/次 | -75%数据量 |
| 首屏加载时间 | 2.5秒 | 1.2秒 | -52% |
七、总结
小程序性能优化的核心是:减少首屏加载的内容。
- 分包加载:主包只放TabBar页面
- 图片懒加载:首屏不展示的图片延迟加载
- setData合并:减少渲染次数,控制数据量
- 分页加载:首屏只加载必要数据
首屏加载时间每减少0.5秒,用户的留存率就提升一个档次。
下一篇,我们来聊聊数据库索引设计------从0到62万条记录的查询优化。
评论区聊聊:你的小程序首屏加载时间是多少?怎么优化的?