小程序性能优化
-
分包
合理的分包可以明显的加快第一次打开小程序的速度, 减小主包的代码体积- 在app.json 中定义subPackages。
- 配合 preloadRule (预加载分包的规则), 可以做到无缝打开分包页面
- 配合 wx.onLazyLoadError , 监听分包下载失败,从而导致分包页面白屏
-
组件懒加载
- 在app.json 中定义"lazyCodeLoading": "requiredComponents"
- 在具体的页面json 文件中, 定义到componentPlaceholder 字段下的组件均会进行懒加载。
- 注意: 懒加载会改变组件生命周期的表现。 例如: 一个组件在未懒加载时, 组件的show 方法会早于页面的onShow 方法, 使用了懒加载后, show方法可能不会执行。
-
内存占用优化:
-
控制页面栈的数量
- 在页面栈数量较多时,可以使用wx.reLaunch、wx.switchTab、wx.redirectTo来优化页面栈数量。例如: 在一次完整的提交流程后, 跳转到成功页面, 在点击返回按钮时,直接使用relaunch 来进入首页。
-
全局变量控制
- 尽量少使用globalData
- 如果有必要,请及时清除,并且注意非常规流程是否清除
-
优化内存泄漏
-
定义在page方法外的变量注意内存占用(防止占用内存较大,而且不会被GC)
-
// 定义在这里的对象不会被GC const customData = {} Page({ })
-
-
setData 优化。 参考文章
- 多次setData操作合并。 因为多次调用setData默认是不会进行合并的, 会设计到多次和wxml通信过程,相对较耗时。
- setData 中data变量尽量只覆盖wxml需要的变量, 非渲染使用的变量可以直接挂载到this中的某个变量上。
- 在自定义组件中, 可以使用pureDataPattern: /^_/ 来优化data 大小
- 在优化老代码时, 可以通过开发者工具中体验评分功能(路径: 详情 --> 性能质量 --> 体验评分)来具体定位哪些data 字段是不需要的。
-
wxml 优化
- 减少wxml 的大小, 可以优化内存占用, 所以尽量使用wx:if 来优化不展示的节点或者自定义组件。
-
图片资源优化
- 图片均通过cdn来引入
- 图片尽量压缩
- 懒加载图片资源:在image 标签中使用lazy-load来控制
-
音视频资源优化
- 音视频资源通过cdn来引入
- 进行懒加载控制,用户没有点击播放时,尽量控制资源的加载。主要是通过控制src 属性, 存在src属性就会加载资源。
- 当存在音视频资源的列表时, 尽量共用一个context上下文, 通过切换src 来实现音视频资源的切换。
-
有长列表需求可以引入虚拟列表
- 如果不想额外引入插件, 可以通过createIntersectionObserver 来模拟一个虚拟列表的控制
小程序音频相关
- 针对iphone 设备的静音播放
wx.setInnerAudioOption({
obeyMuteSwitch: false,
mixWithOther: false
})
- 不要再page函数外面去创建音频上下文,尽量直接在onLoad里面生成一个挂载到this对象上面的上下文
// 这里定义的上下文对象是不会GC的
const innerAudioContext = wx.createInnerAudioContext({
useWebAudioImplement: false
})
page({
global: {}
onLoad() {
// 这样定义页面清除后,会清空
this.global.innerAudioContext = wx.createInnerAudioContext({
useWebAudioImplement: false
})
}
})
- 尽量使用onCanPlay来监听是否可以播放, 不要直接innerAudioContext.play。 这里只针对多个音频,切换了src后的播放, 一个音频就直接play就行
if (this.global.innerAudioContext.src !== src) {
const contextPlay = () => {
this.global.innerAudioContext.play()
this.global.innerAudioContext.offCanplay(contextPlay)
}
// 需要播放的时候这样处理
this.global.innerAudioContext.onCanplay(contextPlay)
} else {
this.global.innerAudioContext.play()
}
- onUnload 时清除监听器
this.global.innerAudioContext.offEnded()
this.global.innerAudioContext.offError()
this.global.innerAudioContext.destroy()
小程序视频相关
-
视频无法全屏(现象: 点击播放只有声音没有全屏图像)
- 主要出现在多视频,同时共用同一个视频context的情况下.
-
<video id="video" class="video" src="{{videoSrc}}" bindfullscreenchange="fullscreenchange" bindloadedmetadata="handelLoadedMetaData" ></video> -
playVideo(e) { const { url } = e.detail const curVideoSrc = url if (this.data.videoSrc === curVideoSrc) { this.videoCtx.requestFullScreen({ direction: 0 }) this.videoCtx.play() return } if (this.data.videoSrc && this.videoCtx) { this.videoCtx.stop() // 停止正在播放的视频 } this.videoCtx = wx.createVideoContext('video') this.setData({ videoSrc: curVideoSrc }) }, fullscreenchange(e) { if (!e.detail.fullScreen) { this.videoCtx.pause() } }, handelLoadedMetaData(e) { // 元数据加载完成后, 调用全屏和播放 this.videoCtx.requestFullScreen({ direction: 0 }) this.videoCtx.play() },
-
多视频资源怎么优化内存占用
- 尽量在一个page中共用一个video 上下文。 同时在视频需要播放的时候再加载视频资源(可以通过控制video 的src是否有值来实现)
-
视频的context 在组件中无法使用
- 需要绑定this, wx.createVideoContext('video', this)
小程序状态管理
总体架构: 通过发布订阅模式来建立一个数据中心,然后页面与数据中心建立绑定关系, 通过相应的方法获取数据信息或者设置数据信息。