做小程序这几年,我越来越觉得性能优化是个「说起来重要、做起来次要、上线后不要」的事。很多项目在开发阶段功能跑通就完事了,等用户量上来,投诉「卡」「慢」「白屏」的时候,才回头翻代码。这篇文章不讲大道理,就聊聊我在实际项目里踩过的坑和真正有效的几招。
先搞清楚卡在哪
优化最怕瞎猜。小程序卡顿无非几个来源:逻辑层 JS 执行太久、setData 数据量太大或太频繁、渲染层节点太多、图片资源太重、网络请求串行阻塞。上线前用开发者工具的「性能」面板跑一遍,重点看两样东西:setData 的耗时和频率,以及首屏渲染时间。这两个指标一出来,问题基本就定位了。
setData 是性能第一杀手
小程序的逻辑层和渲染层是分开的,每次 setData 都要跨线程通信,数据量越大、调用越频繁,卡顿越明显。我见过最夸张的代码是监听滚动事件,每帧都 setData 一次整个列表。改法很简单:
// 反例:整包更新
this.setData({ list: newList })
// 正例:只更新变化的字段,用路径写法
this.setData({ 'list[3].title': '新标题' })- 只传变化的数据,别把整个 data 对象扔进去
- 高频场景(滚动、输入)做节流,100ms 一次足够
- 纯展示、不需要响应式更新的数据,直接挂在
this上,不走 data - 列表渲染用
wx:key,避免整表重排
首屏白屏,八成是包太大
小程序主包有 2MB 限制,很多人一上来把所有页面、图片、第三方库全塞主包,首屏加载自然慢。分包加载是最直接的手段:
{
"pages": ["pages/index/index"],
"subpackages": [
{ "root": "packageA", "pages": ["detail/detail"] }
],
"preloadRule": {
"pages/index/index": { "network": "all", "packages": ["packageA"] }
}
}主包只留首页和公共资源,详情页、个人中心这些低频页面拆到分包,配合 preloadRule 在空闲时预下载。另外,图片别直接放包里,走 CDN,该用 WebP 就用 WebP,首屏大图加个骨架屏,体感快很多。
长列表别硬渲染
商品列表、聊天记录这种几百上千条的数据,一次性 wx:for 渲染出来,节点数直接爆炸。我的做法是分页加载 + 可视区域裁剪,只渲染视口附近的数据。如果不想自己造轮子,社区有成熟的虚拟列表组件,但要注意它们对动态高度的支持程度,复杂场景还是自己写更稳。
网络请求别串行
首屏往往要拉好几个接口,很多人写成 await 一个接一个,白白浪费时间。互不依赖的请求用 Promise.all 并发发出去,能省一半以上时间。另外接口返回的数据结构尽量精简,后端别一股脑返回几十个字段,前端用不上的字段在传输层就砍掉。
几个容易被忽略的细节
- 定时器和事件监听记得在
onUnload里清掉,否则页面销毁了还在跑 - 避免在
onPageScroll里做复杂计算 - 自定义组件开启
styleIsolation,减少样式污染和重排 - 能不用
rich-text就别用,解析成本不低
性能优化没有一劳永逸的方案,它是个持续的过程。我的建议是:把性能指标纳入每次发版的检查清单,别等用户骂了才动手。毕竟用户对「卡」的容忍度,比你想象的低得多。

评论 (0)
还没有评论,快来抢沙发吧~