小程序太慢被用户骂?我是这样优化的

小程序开发性能优化用户体验微信开发
老夫撸代码
老夫撸代码
-- 次浏览

去年我们公司的小程序被用户在应用商店评论区骂惨了:"卡得要死"、"加载半天"、"还不如网页版"...

作为主要开发者,我压力山大。花了 3 个月时间专门做性能优化,总算把用户评分从 2.1 分拉到了 4.3 分。

今天分享一下我在小程序性能优化上踩过的坑和总结出来的经验,希望能帮大家少走弯路。

我踩过的性能坑

第一个坑:代码包太大,启动慢得要命

刚开始做小程序时,我把所有功能都塞在主包里,结果代码包达到了 1.8M。用户打开小程序要等 5-6 秒,体验极差。

后来才知道微信有分包机制。我把非核心功能拆分到分包里,主包只保留首页和登录相关的代码,大小压缩到了 500K。启动时间从 6 秒降到了 2 秒。

具体做法

  • 把商城、个人中心、设置等模块拆分成独立分包
  • 图片资源能放 CDN 的都放 CDN,不要打包到代码里
  • 定期清理没用的组件和样式文件

第二个坑:setData 用法不当,页面卡顿

我以前习惯每次数据变化就调用一次 setData,结果页面经常卡顿。特别是列表页面,滚动时会明显感觉到掉帧。

后来学会了批量更新数据,把多次 setData 合并成一次。还有就是只更新变化的字段,不要整个对象都传。

血泪教训

// 错误做法 - 频繁调用setData
this.setData({ loading: true });
this.setData({ userInfo: res.data });
this.setData({ loading: false });

// 正确做法 - 批量更新
this.setData({
  loading: false,
  userInfo: res.data,
});

第三个坑:网络请求没有缓存,重复加载

我们的小程序有个配置接口,每次进入页面都会请求一遍。后来发现这个配置基本不变,完全可以缓存起来。

现在我会把不常变的数据缓存到本地,设置合理的过期时间。用户体验提升很明显,特别是网络不好的时候。

现在我是怎么优化的

启动优化:让用户秒开你的小程序

分包策略

  • 主包只放首页、登录、基础组件
  • 按业务模块拆分分包,比如商城、个人中心、活动页面
  • 每个分包控制在 500K 以内

预加载优化

  • 在 app.json 里配置 preloadRule,用户浏览首页时预加载可能访问的分包
  • 引导用户"添加到我的小程序",提高缓存命中率

代码优化

  • 开启懒加载:"lazyCodeLoading": "requiredComponents"
  • 压缩图片,能用 webp 就用 webp
  • 删除 console.log 和无用代码

渲染优化:告别卡顿和白屏

setData 优化

// 我现在的做法
const updateData = {};
if (needUpdateUser) updateData.userInfo = newUserInfo;
if (needUpdateList) updateData["list[0].status"] = "active";
if (Object.keys(updateData).length > 0) {
  this.setData(updateData);
}

条件渲染优化

  • 初始不显示的内容用 wx:if,避免无意义的渲染
  • 频繁切换的内容用 hidden,避免重复创建销毁
  • 长列表使用虚拟滚动,我用的是 recycle-view 组件

骨架屏: 以前用户看到白屏会以为程序卡死了。现在我在所有需要加载数据的页面都加了骨架屏,用户体验好了很多。

网络优化:减少等待时间

缓存策略

// 我的缓存工具函数
const cache = {
  get(key) {
    const data = wx.getStorageSync(key);
    if (data && data.expireTime > Date.now()) {
      return data.value;
    }
    return null;
  },
  set(key, value, expireMinutes = 30) {
    wx.setStorageSync(key, {
      value,
      expireTime: Date.now() + expireMinutes * 60 * 1000,
    });
  },
};

请求优化

  • 合并接口:一个页面需要的数据尽量一个接口返回
  • 预请求:在页面跳转前就开始请求下个页面的数据
  • 失败重试:网络不好时自动重试,不要让用户手动刷新

用户体验优化

加载状态要明确

以前我经常忘记加 loading 状态,用户点击按钮没反应,会以为程序坏了。

现在我的习惯是:

  • 所有异步操作都要有 loading 状态
  • 按钮点击后立即显示 loading,防止重复点击
  • 网络请求失败要有明确的错误提示

交互反馈要及时

震动反馈: 关键操作加上震动反馈,比如删除确认、支付成功等。代码很简单:

wx.vibrateShort({ type: "light" });

Toast 提示: 操作成功或失败都要给用户明确反馈,不要让用户猜。

空状态设计

以前列表为空时就显示个空白页面,用户体验很差。现在我会设计专门的空状态页面:

  • 搜索无结果:显示"换个关键词试试"
  • 网络异常:显示"网络开小差了,点击重试"
  • 列表为空:显示"暂无数据,去看看别的吧"

一些实用的优化技巧

图片优化

懒加载

// 使用intersection observer实现图片懒加载
const observer = wx.createIntersectionObserver();
observer.relativeToViewport().observe(".lazy-image", (res) => {
  if (res.intersectionRatio > 0) {
    // 开始加载图片
  }
});

压缩和格式

  • 能用 webp 就用 webp,体积小很多
  • 图片压缩到合适大小,不要用原图
  • 小图标用字体图标或 SVG

内存管理

及时清理

// 页面卸载时清理定时器和监听器
onUnload() {
  if (this.timer) {
    clearInterval(this.timer)
  }
  if (this.observer) {
    this.observer.disconnect()
  }
}

兼容性处理

机型适配

  • 低端机型降级处理,减少动画和特效
  • 使用 wx.getSystemInfo 获取设备信息,针对性优化
  • 刘海屏适配,使用 safe-area 相关样式

性能监控

现在我会在小程序里加一些性能监控:

// 启动时间监控
App({
  onLaunch() {
    this.launchTime = Date.now();
  },
  onShow() {
    const showTime = Date.now();
    console.log("启动耗时:", showTime - this.launchTime);
    // 上报到后台
  },
});

还会监控页面加载时间、接口响应时间等关键指标,及时发现性能问题。

写在最后

小程序性能优化是个持续的过程,不是一次性的工作。我现在的习惯是:

  1. 开发时就考虑性能:不要等出问题了再优化
  2. 定期检查:每个版本发布前都要测试性能
  3. 关注用户反馈:用户的抱怨往往指向真正的问题
  4. 数据驱动:用数据说话,不要凭感觉优化

经过这次优化,我们小程序的用户留存率提升了 30%,用户评分也从 2.1 分涨到了 4.3 分。虽然过程很痛苦,但结果还是很值得的。

希望我的经验对大家有帮助。如果你也遇到过类似问题,欢迎交流分享!

关注微信公众号

微信公众号二维码

扫码关注获取:

  • • 最新技术文章推送
  • • 独家开发经验分享
  • • 实用工具和资源

💬 评论讨论

欢迎对《小程序太慢被用户骂?我是这样优化的》发表评论,分享你的想法和经验