云裂变营销网

标题: 自学《小程序性能优化实践》的笔记(一) [打印本页]

作者: 匿名    时间: 2023-3-10 10:15
标题: 自学《小程序性能优化实践》的笔记(一)
一、课程链接:https://developers.weixin.qq.com/community/business/doc/0002ce57c346300cccdd3ad835280
二、课程源码链接:https://gitee.com/geektime-geekbang_admin/weapp_optimize
三、理解一些概念
1、小程序优化,主要是指从小程序开始启动到首页完全渲染显示(Page.onReady事件派发),这个过程之间的一个优化。

自学《小程序性能优化实践》的笔记(一)-1.jpg
2、冷启动,小程序在用户设备上是第一次打开,或者是销毁后再次打开。小程序第一次启动及冷启动30分钟以后被系统回收重新再启动,都是冷启动。
3、热启动,相对于冷启动而言,是小程序启动的一种优化机制。小程序进入后台30分钟以内再次进入前台,可直接从后台状态恢复到前台。一些一次性流程都不会有了,如App.onLanuch、Page.onLoad及Page.onReady事件的派发。
四、小程序在启动(冷启动或热启动)流程中的一些优化要点以。
1、页面开始渲染(Page.onLoad事件派发)到首屏渲染完成(Page.onReady事件派发)这中间涉及到的动态数据加载,其加载的数据量有多少,网络请求所需时间是多少,图片等静态资源加载需要的时间有多少,都会影响首屏渲染时间。此时可以使用以下来符合实际启动时候的需求:
1)代码按需注入,小程序仅注入当前访问页面所需的自定义组件和页面代码。(懒加载)
  ①app.json中需要配置"lazyCodeLoading": "requiredComponents"。
  ②启用按需注入后,页面json配置的所有组件和app.json中的全局自定义组件,都会被注入和加载(所以,不用什么组件都写在app.json中)。
  ③插件包和扩展库目前暂不支持按需注入。如果需要实现插件按需加载,可以考虑将插件置于一个分包,并通过「分包异步化」的形式异步引入。
2)用时注入 ,可以指定一部分自定义组件不在小程序启动时注入,而是在真正渲染的时候才进行注入。
① app.json中需要配置"lazyCodeLoading": "requiredComponents"。
②为自定义组件配置占位组件,组件就会自动被视为用时注入组件:
   a)每个页面内,第一次渲染该组件前,该组件都不会被注入;
   b)每个页面内,第一次渲染该组件时,该组件会被渲染为其对应的占位组件,渲染流程结束后开始注入;
   c)注入结束后,占位组件被替换回对应组件。
3)使用独立分包和分包预加载
① 使用分包 | 微信开放文档
② 独立分包,独立于主包和其他分包运行。从独立分包中页面进入小程序时,不需要下载主包。当用户进入普通分包或主包内页面时,主包才会被下载。
  1. app.json中添加配置
  2. "subpackages": [
  3.    {
  4.      "root":"goods", // 分包的地址
  5.      "pages": [ // 指定页面,是分包地址下面的相对地址
  6.        "pages/detail/index"
  7.       ],
  8.      "independent": true // 加上这个配置就是独立分包,不加普通分包。
  9.    }
  10. ]
复制代码
一)影响 ,a)使用getApp()接口的时候,取不到全局的应用实例了,在分包的页面的js文件中顶部添加:
  1. const app = getApp({ allowDefault: true })
  2. // 独立分包中getApp为空,这里设置默认值,允许定义默认的内容
  3. /*app.globalData = {
  4.   Custom:{width:87,height:32,left:320,top:24,right:407},
  5.   CustomBar:60,StatusBar:40,tabbar_bottom: "n"
  6. }*/
  7. app.globalData ={StatusBar:40}
  8. Page({
  9. data: {
  10.    StatusBar: app.globalData.StatusBar+6,
  11.   }
  12. })
复制代码
可以只定义,自己需要的信息: app.globalData ={StatusBar:40}。
b)从独立分包的页面跳到主页面的时候,这个时候主包与主页面也会加载,小程序会帮我们把独立分包中getApp定义默认的内容与原本的信息进行合并
c)作为一个独立的分包,它被加载的时候,主包及主页面还有其他页面其实是不加载的。主包中的组件也是不加载的。
二)独立分包里面使用占位组件,进一步减少独立分包代码包的一个体积以及在主页中使用占位组件。
占位组件,就是给自定义组件安排一个替身,在真实的自定义组件加载并注入之前先用替身展示,以此来进一步优化启动的性能。
a)组件的分包异步化及主页中占位组件的使用。将首页里面用到的所有的自定义组件全部移到一个分包里面,然后再使用占位组件延迟加载它们,这样就可以进一步提高主页的加载速度了。
i. app.json中配置
  1. "subpackages": [
  2.    {
  3.      "root":"index_addons",
  4.      "pages": []
  5.    }
  6. ]
复制代码
ii. 将组件由全局引用改为页面引用,并且进行占位的组件声明。页面或自定义组件对应的 JSON 配置中的componentPlaceholder字段用于指定占位组件
  1. {
  2.   "usingComponents": {
  3.       "stopwatch":"/index_addons/components/stopwatch_nw/index",
  4.   },
  5.   "componentPlaceholder": {
  6.     "stopwatch": "view"
  7. // view是作占位组件的一个名称,占位组件我们可以使用标准组件,也可以使用自定义组件,
  8. // 在使用自定义组件的时候也要求我们先在usingComponents列表内先声明,
  9. // 在stopwatch组件的真身被从index_addons分包里边加载完成以前,它将以view的一个形式进行展示,
  10. // view在这里它是一个万能的占位组件,使用它我们不需要额外的定义,它默认也有一个slot插槽可以容纳一些简单的文本 一些组件
  11. // 一般使用view即可
  12.   }
  13. }
复制代码
b)使用封面页,是一种非技术的优化首页加载性能的方法。它的作用是加载封面页所在的主包里边的所有的基础内容,包括类库,插件和自定义组件等,加载完成之后,跳转到真正的产品首页。它位于主包内,而真正的首页则移动到另外的一个代码包index里面。这种优化方法特别适用于产品比较复杂,分包共用的基础库又比较大,只能放在主包中这样的一个产品小程序。(课程代码小节:5.1)
三)JS代码的分包异步化,小程序提供的分包异步化能力不仅针对组件代码,插件也可以异步化一言以蔽之,另一个分包内的一切,只要我们想使用,都可以通过异步加载的方式拿过来使用。
③分包预加载
在分包的页面,如果想要访问主页,就在该分包里面开启对主包的一个分包预加载,提前加载,方便用户的后续的一个快速访问。
  1. app.json中添加配置
  2. "preloadRule":{
  3.    "goods/pages/detail/index":{  // 页面做key, 分包的root/分包里面的页面的地址
  4.       "network": "all", // 所有网络环境都可以分包预加载,如wifi
  5.       "packages": ["__APP__"] // 对哪些分包实现预加载,此时代表主包
  6.   }
  7. }
复制代码
④总结,a)小程序默认的tabBar以及通过app.json配置文件配置的自定义tabBar都要求图标必须放在本地,不能进行网络化,再加上tabBar页面只能使用wx.switchTab接口进行跳转等等这些原因,tabBar导航栏最好是使用自定义的这种方式去实现。 (课程代码小节:4)  b)所有在项目根目录下的子目录以及文件如果没有被分包瓜分的话,默认都会打包到主包里面,包括app.json中启用的全局插件 组件及第三方的类库等等这些也都会打包到主包里边,所以主包一般情况下只放一个首页以及基础的不能再基础不能再删减的内容像其他的这些页面其他的这些自定义组件,在分包实践里面完全可以移到分包里面去。c)对于分包的一个配置只需要指定一个root目录,该目录下所有的文件它都会自动被分割到这个分包里面,对于准备在微信中分享的相对独立的页面,准备在微信里 微信群 朋友圈 然后分享传播的这些页面适合定义为独立分包。d)独立分包有返回主页的按钮,如果用户对当前这个产品他感兴趣,他返回首页的几率会比较大,所以在这种情况下,一般我们在独立分包里面设置对主包的一个分包预下载。e)对于准备随时用于社交传播的页面,它代码包的体积是越小越好。
4)
使用骨架屏,页面的内容和渲染的时间并没有减少,用户等待的时间还是那么多,只是增加了用户等待时候的体验。(静态导航页适合使用初始渲染缓存,动态详情页适合使用骨架屏;用了骨架屏以后就不要再使用初始渲染缓存了。反之也是一样的。)
5)初始渲染缓存,骨架屏是在页面完全加载以后,由微信开发者工具负责生成的一个色块状页面结构,在运行时与骨架屏对应的还有一项技术就是初始渲染缓存。
初始渲染缓存,在小程序页面的第一次被打开的时候,微信就将这个页面的初始渲染的结果记录下来,然后写入到一个临时的缓存区域里面,在这个页面第二次打开的时候,微信它查看缓存里面有没有这个页面,如果是有 直接就把这个页面展示给用户,缓存的页面它是无法响应用户的交互事件的,需要等到这个页面真实渲染完成以后这个页面才可以正常访问。
所有的原生组件它都不在这个缓存之列。
初始渲染缓存只适合这个页面节点数量比较少、比较简单、内容不经常变化、用户又经常访问同时wxml节点的结构又非常简单的这样的一些入口页面去使用。
用了骨架屏以后就不要再使用初始渲染缓存了。反之也是一样的。
用于提供导航功能的一个首页或者是二级页面,一般适合使用初始渲染缓存。而这个页面经常变化的时候,时效性较高的动态详情页面,这种页面它适合使用骨架屏,当然了如果这个页面想让用户尽早看到内容的话。(静态导航页适合使用初始渲染缓存,动态详情页适合使用骨架屏)
② 在页面json文件中配置静态初始渲染缓存 "nitialRenderingCache":"static" 。静态初始缓存以页面初始的data数据与页面里面的wxml标签代码共同渲染成一个页面在本地缓存,在下一次用户访问页面的时候,不必等逻辑层代码初始化完毕它就会将缓存的页面内容先发给用户展示,在一定程度上,初始渲染缓存的页面相当于是一个静态化的本地化的骨架屏页面。
③  在页面json文件中配置动态初始渲染缓存"nitialRenderingCache":"dynamic"。在页面加载完成以后,通过调用setInitialRenderingCache的一个方法设置需要动态缓存的数据。
  1. onReady(){
  2.   // 拉取轮播图数据
  3.   ;(()=>{
  4.     wx.request({
  5.         url,
  6.         success: res=>{
  7.           if(res.errMsg==='requset:ok'){
  8.                const {swipers} = res.data.data
  9.                 this.setData({swiperlist:swipers})
  10.                    // 数据加载完成以后 ,设置动态缓存数据
  11.                    this.setInitialRenderingCache({
  12.                         swiperlist:swipers // swiperlist 是在data{}中声明的变量。
  13.                    })
  14.                }
  15.             },
  16.         fail:console.log
  17.      })
  18.   })
  19. }
复制代码
6)对于长列表页面,用户第一次仅需看到上面的首屏内容,下面需要滑动才能看到的内容是没有必要一次性渲染给用户的。
使用recycle-view组件渲染长列表内容
五、运行时的视图渲染优化要点
1)重渲染与自定义组件优化
重渲染机制通过setData传递数据,它不仅受到底层传输通道窄小的限制,它还受到设备渲染能力的一个限制。这个数据越大节点越多越复杂。它渲染也就越慢,而渲染一慢在用户侧看来它表现起来就是卡顿,操作反馈不及时。因此我们可以将这个界面功能进行组件化处理,将频繁变化的数据封装在一个个的单独的组件里边,同时去掉一些不必要的数据设置,减少每次setData传递的一个数据量,也可以提升这个视图的渲染效率,还有通过wxs脚本改写组件,让可以在这个视图层里面完成的代码逻辑,就在这个视图层里面进行完成。
2)使用页面容器
,使用这个组件,在iOS用户做出左滑手势及Android用户单击物理返回键以及在代码里边调用了wx.navigateBack接口的时候仅是关闭这个容器,它并不会跳出当前这个页面。它可以放在自定义的组件里面,像一个独立的组件那样去定义和使用。
3)优化视图页动画效果
第一种是使用Animation对象,实现了一个CSS动画;
第二种是使用页面或组件对象,拥有的animate方法实现的关键帧动画;
第三种是使用滚动事件驱动的响应式动画;
最后一种是通过WXS脚本,实现了一个样式动画。
对于第一种是小程序最早支持的一种动画方式,它的效率是最低的。第二种以animate方法实现的关键帧动画,它拥有更好的性能和更容易控制的接口,它是目前推荐选择的方式,从效率上来讲,它并不是最高效的一种方式。第三种以滚动事件驱动的响应式动画,它的用户体验感最好,使用也简单,是一种推荐的低成本创建响应式页面效果的一种方式。第四种也是最后一种,通过WXS脚本实现样式动画,这种方式效率最高,因为它不需要逻辑层的参与改变视图层组件的样式,在视图层里边就可以自己完成动画了。




欢迎光临 云裂变营销网 (https://www.yunliebian.com/yingxiao/) Powered by Discuz! X3.4