代码包体积优化
1.合理使用分包加载
1.1独立分包
小程序中的某些场景(广告页、活动页、支付页等),通常功能不是很复杂且相对独立,同时对启动性能有很高的要求。
独立分包可以独立于主包合其他分包运行。从独立分包页面进入小程序时,不需要下载主包。
因此将要求高性能的页面放到独立分包中,优化启动速度,提高用户体验。
1.2分包预下载
1.3分包异步化
可以将小程序的分包从页面粒度细化到组件甚至文件粒度。这使得本来只能放在主包页面的部分插件、组件和代码逻辑可以剥离到分包中,并在运行时异步加载,从而进一步降低启动时所需要的包大小和代码量。
- 组件异步化核心是通过异步加载分包模块的组件同时配合占位组件,来实现组件异步加载完成后进行替换。
- js逻辑异步化的核心在于使用require方法进行注册。
分包异步化能有效解决主包大小过度膨胀的问题。
2.避免非必要的全局自定义组件和插件
在app.json中通过usingComponents 全局引用的自定义组件和通过 plugins 全局引入的插件,会在小程序启动时随主包一起下载和注入js代码,影响启动耗时。
3.控制代码包内的资源文件
小程序代码包在下载时,会使用ZSTD算法进行压缩,图片、音视频、字体等资源文件会占用较多代码包体积,并且通常难以进一步压缩,对于下载耗时的影响比代码文件打大得多。
静态资源尽量部署到CDN中,并使用URL进行引入(除非要做离线展示)
4.及时清理无用代码和资源
除了工具默认忽略或开发者明确声明忽略的文件,小程序打包回将工程目录下所有文件都打入代码包中。
不定期的分析代码包的文件构成和依赖关系,以此优化代码包大小和内容。或使用webpack、rollup等打包工具,对小程序代码进行预处理,可以利用tree-shaking等特性去除冗余代码,也要注意防止打包时引入不需要的库和依赖。
代码注入优化
1.启动过程中减少同步API调用
在小程序启动过程中,会注入开发者代码并顺序同步执行:App.onlaunch,App.onShow,Page.onLoad,Page.onShow
在小程序初始化代码和上述启动相关的几个声明周期中,应尽量减少或不调用同步API。绝大多数同步API会以 Sync 结尾,但有部分特例,比如 getSystemInfo (带不带sync都是同步的)
同步API虽然使用简单,但是会阻塞js现成,影响代码执行。
常见的有:
** -- getSystemInfo / getSystemInfoSync**
- 由于历史原因,这两个都是同步的API,同时这两个接口承载过多内容,单次调用耗时会比较长,不建议首屏调用,并且应该在调用后设置缓存,避免重复调用。
** -- getStorageSync / setStorageSync**
- 启动过程中多次续写也会显著影响小程序注入耗时
- 简单数据共享不建议使用,建议使用 globalData 完成
2.启动过程中避免CPU密集型任务
在小程序初始化代码和启动相关的几个生命周期中,应避免执行复杂的运算逻辑。复杂运算也会阻塞当前js线程,影响启动耗时。建议将复杂的运算延时到启动完成后进行。
首屏渲染优化
1.使用 按需注入 和 用时注入
2.启用 初始渲染缓存
3. 避免引用未使用的自定义组件
4.精简首屏数据
对于复杂页面可以采用 渐进式渲染 优先展示页面关键内容,对于非关键内容或者不可见部分延迟更新。
同时,与视图渲染无关的数据尽量不要放在 data 中,避免影响页面渲染时间。
5.提前首屏数据请求
小程序提供了如下能力:
数据预拉取
- 预拉取能够在小程序冷启动时通过微信后台提前向第三方服务器拉取业务数据,当代码包加载完时可以更快的渲染页面,减少用户等待时间,从而提升小程序的打开速度
- 需要在后台进行配置
周期性更新
- 周期性更新能够在用户未打开小程序的情况下,也能从服务器提前拉取数据,当用户打开小程序时可以更快的渲染页面,减少用户等待时间,增强在弱网条件下的可用性
- 同样需要在后台进行配置
6.缓存请求数据
7.骨架屏
发版频率控制
合理的规划版本发布,可以让微信拉取小程序信息更快,因为微信首次拉取小程序信息需要进行版本控制以及监控版本更新。
同时频繁的版本发布会让用户频繁的进行更新,用户会经常体验“首次加载”
小程序运行时优化
1.合理使用setData
setData 是小程序最容易造成性能问题的接口,尽管在使用 uniapp 的情况下,本质上组件更新最终还是会依赖 setData
1.1 data 只应包含渲染相关的数据
- 渲染无关的数据直接丢到实例的this上
- 避免使用data在页面或者组件间进行数据共享
- 渲染间接相关的字段应该设置为纯数据字段(纯数据字段不会参与页面渲染,也就不会和UI线程通信,节约时间),然后通过 observers 控制逻辑更新,但是不能滥用,非data的数据禁止使用
1.2 控制 setData 的频率
- 每次 setData 都会触发逻辑层虚拟DOM树的遍历和更新,也可能导致触发一次完整的页面渲染流程
- 过于频繁(遍历过程中setData)会导致对端始终处于繁忙状态,UI交互无法完成,导致用户明显感觉页面卡顿
1.3 控制 setData 合适的范围
- setData 只会引起 当前组件 和 当前组件的子组件 更新,因此频繁更新(秒杀倒计时等)的区域应抽离为单组件
- 必要时增加 css contain减少重绘次数和回流范围(layout将回流限制在一定范围内)
1.4 setData只传递变化的部分
- 如果将整个data传入setData,会增加页面更新开销和数据通信耗时,导致页面卡顿
1.5 阻止后台页面setData
- 小程序挂在后台的页面数据是处于激活状态的,并且小程序的逻辑线程和UI线程都是共享的同一个线程,因此后台的逻辑更新和UI更新,也会影响前台的卡顿
- 所有的更新逻辑应控制在页面 onHide 时暂停,在 onShow 后继续
- 避免后台高频操作,比如定时器
渲染性能优化
1. 适当监听页面或组件的scroll事件
只要用户在 page 构造是传入了 onPageScroll 监听,基础库就会认为开发者需要监听页面scroll事件。此时,事件会以很高的频率从视图层发送到逻辑层,存在一定的通信开销。
使用时需要注意:
- 非必要不监听scroll
- 不要保留空的 onPageScroll 函数
- 实现与滚动相关动画时,优先考虑 滚动驱动动画 或 wxs响应事件
- 避免滚动事件中频繁调用setData或同步API
- 避免滚动事件中执行CPU密集型任务
2.选择高性能的动画实现方式
- 优先使用css渐变、css动画或小程序提供的动画实现方式
- 避免使用setData实现动画,因为这样会导致频繁调用,极易出现卡顿。如果不得不使用,应改为组件级setData
3.使用 intersectionObserver 监听元素曝光
4.控制WXML节点数量和层级
5.控制在page构造时传入的自定义数据量
页面切换优化
1.避免在 onHide/onUnload 中执行CPU密集型任务
2.首屏渲染优化
3.提前发起数据请求
跳转页面时,可以提前发起请求,对下一个页面做一些准备,使用 eventChannel 将数据传输给下一页。
4.控制预加载下个页面的时机
小程序页面加载完成后,会预加载下一个页面。默认情况下,小程序框架会在当前页面 onReady 触发 200ms 后触发预加载。
在安卓上由于渲染线程中的webview共用同一个线程,因此在预加载下一个页面时会阻塞当前页面setData的执行,造成当前页面和用户交互产生延迟,影响用户看到页面完成内容的时机。
handleWebviewPreload 有如下取值:
- static:页面onready后200ms触发预加载
- auto:线程空闲时触发预加载(通过requestAnimateFrame执行判断是否空闲)
- manual:手动预加载,在调用 wx.preloadWebview() 后执行下一页面预加载
注意:handleWebviewPreload仅支持安卓,低版本配置不生效。
资源加载优化
1.控制图片资源大小
2.避免滥用image组件的widthFix/heightFix 模式
会在图片加载完成后改变图片的尺寸,会引起页面大规模重排,造成抖动。
内存优化
1.定期处理内存告警问题
2.处理内存泄漏操作
版权归原作者 Neo 丶 所有, 如有侵权,请联系我们删除。