这章谈谈在开发中的一些常用优化方案
# setData
先科普下小程序架构,来源于官方介绍:
# 双线程设计
- 逻辑层:创建一个单独的线程去执行 JavaScript,在这个环境下执行的都是有关小程序业务逻辑的代码
- 渲染层:界面渲染相关的任务全都在 WebView 线程里执行,通过逻辑层代码去控制渲染哪些界面。一个小程序存在多个界面,所以渲染层存在多个 WebView 线程

# 双线程通信
前面我们知道,逻辑层和渲染层的通信会由 Native (微信客户端)做中转,逻辑层发送网络请求也经由 Native 转发。

- 1.在渲染层把 WXML 转化成对应的 JS 对象。
- 2.在逻辑层发生数据变更的时候,通过宿主环境提供的 setData 方法把数据从逻辑层传递到 Native,再转发到渲染层。
- 3.经过对比前后差异,把差异应用在原来的 DOM 树上,更新界面。
再科普下 setData 做的事情:
在数据传输时,逻辑层会执行一次 JSON.stringify 来去除掉 setData 数据中不可传输的部分,之后将数据发送给视图层。同时,逻辑层还会将 setData 所设置的数据字段与 data 合并,使开发者可以用 this.data 读取到变更后的数据。
我们知道,用户的一次交互,如点击某个按钮,开发者的逻辑层要处理一些事情,然后再通过 setData 引起界面变化。这样的一个过程需要四次通信:
- 渲染层 -> Native(点击事件)
- Native -> 逻辑层(点击事件)
- 逻辑层 -> Native(setData)
- Native -> 渲染层(setData)
因此频繁调用,视图会一直更新,阻塞用户交互,这样的操作流程会导致用户体验卡顿,引发性能问题。
知道原理后,我们可以采取以下方法:
- 首次加载 —— 读取接口的时候,尽量不要做 setData 操作
- 合并更新 —— 避免频繁的去 setData
- 局部更新 —— 减少数据传递时间和渲染效率
- wxs —— 在一定程度上缓解了微信小程序架构中跨线程通信的开销,具体可以查看官方文档 wxs
# 尽可能多用原生组件
因为小程序是 Hybrid 应用,除了 Web 组件的渲染体系,还有原生组件的渲染。
它有几个好处:
- 绕过 setData、数据通信和重渲染流程,使渲染性能更好。
- 扩展 Web 的能力。比如像输入框组件(input, textarea)有更好地控制键盘的能力。
- 体验更好,同时也减轻 WebView 的渲染工作。比如像地图组件这类较复杂的组件,其渲染工作不占用 WebView 线程,而交给更高效的客户端原生处理。
它也有坏处:
- 原生组件的层级会比所有在 WebView 层渲染的组件要高
- 样式无法应用到原生组件上
# 分屏渲染,延迟加载
- 首屏模块和非首屏模块。简单说就是首页接口合理拆分,先加载首屏模块,再夹在非首屏模块,以此确保首屏内容以最快速度呈现。一次大量的setData会导致页面的卡住。
- 弹窗、右侧浮窗可以等主页面渲染完成再延迟1-2秒加载数据。
- 如果首页比较长,位于3屏之后的数据,有部分用户不一定会查看到的,可以延迟加载也可以选择滚动到距离底部“100px”再加载(例如首页“精选视频”模块),适当减少请求。
# 骨架屏
Skeleton Screen,相比于 loading 菊花图效果,骨架屏只是从感官上提升了用户体验,对性能没太多帮助(可能会消耗更多),相对于菊花图技术上会稍微复杂,请自行取舍。

# 动画效果
由于架构的原因,频繁执行耗时逻辑改变视图,会造成动画掉帧。尽量用 css3 的动效,比如 fade-in-right/fade-out-right。
# 分包策略
小程序可以分主包和分包,主包是入口的文件包,其余可以归为分包。
当用户第一次打开小程序,会先下载好所有代码,然后再加载页面;当用户再次进入时,会直接使用已下载的代码,省去了代码下载的过程,打开速度更快。
微信小程序每个分包的大小是2M,总体积一共不能超过8M。 支付宝小程序每个分包的大小是2M,总体积一共不能超过4M。
我们公司最近开发的一款小程序,
- 在使用分包之前,压缩后的代码量大概是 2.23M,每个新用户第一次都需要下载的全部代码才能进入页面,差不多花费3秒时间才进入小程序。
- 使用分包机制后,主包大小控制在 1M 左右,平均1秒左右就可以进入小程序,下载时间大约降低了60%。
文件结构:
├── apis ├── components ├────… ├── pages 主包根目录 ├────index 首页 ├────my 我的 ├────… ├── subPages 分包根目录 ├────search 搜索页分包 ├────shopcart 购物车页分包 ├────…
# 本地图片压缩
- 推荐一个网站tinypng,非常好用,它采取更严格的压缩算法在不失真情况下做到最优的输出。
- 转成base64。
- 小程序的
image组件可以支持 JPG、PNG、SVG、WEBP、GIF 等格式。尽可能利用 WEBP 格式优势,对比无损压缩体积比 PNG 小 26%,有损压缩体积比 JPEG 小 25-34%。 - 利用
image组件自带lazy-load懒加载属性(但是有要求:在即将进入一定范围(上下三屏)时才开始加载)。
