收藏
评论

使用占位组件官方


你好,我是李艺。

上节课我们主要学习了分包 独立分包、分包预下载以及完全自定义的方式实现tabBar导航栏。这节课我们继续优化独立分包,在独立分包goods里边使用占位组件进一步减少独立分包代码包的一个体积以及在主页中使用占位组件。

首先我们看一下问题,目前我们在这个项目里边已经启用了懒加载机制,代码是按需加载并注入的,但是这还不够。前面我们提到过还可以使用占位组件,就是给自定义组件安排一个替身,在真实的自定义组件加载并注入之前先用替身展示,以此来进一步优化启动的性能,接下来我们看项目实践。


首先看实践一,组件的分包异步化及主页中占位组件的使用。

目前我们在主页上使用的自定义组件stopwatch,是在app.json配置文件里面进行配置的,是以全局的方式在小程序里面进行使用的,小程序首页要尽快让用户看到,至于像导航是可以让用户在看到这个页面以后再展示的,所以这个地方还有优化的空间。

前面我们通过lazyCodeLoading配置给这个项目启用了懒加载,但是我们在这个页面里面用到的自定义的组件,例如tab-bar组件,小程序还是会在页面初始化之前进行加载,这种情况下我们可以将首页里面用到的所有的自定义组件全部移到一个分包里面,然后再使用占位组件延迟加载它们,这样就可以进一步提高主页的加载速度了,

具体怎么实现,首先第一步我们需要在app.json配置文件里边创建一个名称为index_addons一个组件分包,代码包我们可以没有页面也没有关系,不影响它作为一个分包单独存在;

第二步就是我们要修改我们主页的配置,将组件由全局引用改为页面引用,并且进行占位的组件声明,在声明占位组件的时候只需要在页面配置文件里面,在componentPlaceholder这个节点下面设置组件的替身即可,componentPlaceholder是占位组件声明的节点名称,在我们主页面配置里边stopwatch是组件名称,这个view是欲用作占位组件的一个名称,占位组件我们可以使用标准组件,也可以使用自定义组件,在使用自定义组件的时候也要求我们先在usingComponents列表内先声明,在stopwatch组件的真身被从index_addons分包里边加载完成以前,它将以view的一个形式进行展示,view在这里它是一个万能的占位组件,使用它我们不需要额外的定义,它默认也有一个slot插槽可以容纳一些简单的文本 一些组件;

第三步也是最后一步,就是在这个页面中添加wxml代码与JS代码,在代码里面我们使用到的问号,我们之前也使用过,是ES6语法里面的可选链语法,它可以防止用户在查询不到真正的stopwatch组件的时候进行操作而报错.

关于占位组件的调试在这里我们说明一下,在测试的时候可以将模拟器的网络设置为2G并清除缓存,可以很明显的看到页面加载完成以后,用户都可以看到整个的页面了,自定义组件才加载完成并将占位组件给它替换掉,在这个项目的详情面板里,在本地设置这个标签里面有一个懒加载占位组件测试这样一个选项,我们将这个选项勾选,方便我们进行占位组件的一个测试,只有在项目中开启了按需注入以后,在这个项目设置面板里面才会出现这样的一个选项,勾选以后按需注入的组件将会停止注入,页面停止在占位组件状态便于我们查看占位组件的替身的表现,完成测试以后我们还可以将其反选,这样就又可以看到正常的一个运行状态了,如果勾选以后发现模拟器的表现与预期不符的话,我们可以选择工具栏里面的清缓存按钮清扫一下缓存,之后可以再试。

这里有一个问题我们讨论一下,我们可以无限制地使用用户设备资源吗?无论是stopwatch组件还是stopwatch_wxs组件,无论是基于定时器实现还是基于设置帧动画的requestAnimationFrame方法实现,我们对用户设备的资源的使用都应该怀有敬畏之心,始终都应当克制,我们只需要取用可以满足我们实现产品需求所需要的最低的设备资源可以了,甚至有时候我们还要牺牲一点点,表面上的一些漂亮来换取整体上的一个流畅,举个例子,在两个组件里面,如果我们将渲染时间、间隔时间设置的很短,例如定时器我们设置为33毫秒间隔,这基本上是想每两帧就渲染一次,在每一次requestAnimationFrame回调函数里面都调用callMethod方法然后进行渲染,这样改动以后会让这个页面非常的卡顿,甚至到了在模拟器里边都无法运行的这样一个地步,当然了卡顿的程度与我们用的电脑设备也有关系,与电脑同时开了多少程序也有关系,解决的办法其实也很简单,我们只需要将渲染的间隔时间稍微调大一点点就可以了。

接下来我们进行实践一的代码演示。

首先我们要明确一下,我们要使用占位组件技巧的组件是哪一个,目前在我们这个项目里边,在主页里边使用了一个stopwatch这样的组件,这个组件先前我们是在app.json全局的配置文件里面进行引用的 ,在这个地方我们要对它进行一个占位的,这样的一个组件的声明一个使用,首先放在这个地方就不合适了,我们需要首先创建一个分包,在这个地方我们可以拷贝一个配置节点出来,然后root就写我们项目底下有一个叫做index_addons,写这个名字,我们将这个目录下面所有的文件都作为一个分包,然后存在 pages可以没有文件 没有页面也是可以的,然后independent独立的设置我们给它去掉,设置完成以后组件的声明放在这里就不合适了,我们给它移到我们的主页面里面的json配置里面,移到这个里面来 然后拷贝到这个地方,这个就已经完成了组件的一个引用了,我们现在刷新测试一下,看它的一个表现。

打开这个项目的详情面板可以查看我们关于自定义的组件一个选项,我们可以在这地方可以看一下,目前这个地方没有的话我们再确认一下配置文件里面有没有懒加载的一个配置,现在好像没有,没有的话没关系,可以再给它加上lazyCodeLoading等于requiredComponents,加上以后我们再单击编译,此时我们再查看这个项目的详情面板这个地方就出来了一个新的选项,就是懒注入占位组件的一个测试,这个地方出来以后,我们可以看到我们这个组件现在其实它还没有正常的一个工作,因为它现在其实在分包里面,它其实不在我们主包里面了,我们现在的主页仍然是在主包里面。

接下来我们要对我们组件进行一个占位组件的声明,这个地方要用componentPlaceholder这样的一个配置,前面我们要写我们组件的名字,然后后边我们要用作占位组件的这样的一个组件名字,这个我们可以自定义,也可以用这个标准组件,因为标准组件view它就是一个标准组件或者是我们用自定义组件也是可以的,用自定义组件的话,首先就是我们要去创建一个组件,而且这个组件要跟我们当前这个页面要在一起,然后这个index下面就有一个pages对不对,我们可以在这个地方新建一个目录,components创建这样的一个目录,然后在下面我会再创建一个子目录,stopwatch_ph我们可以写个后缀是ph用这样的一个后缀,再创建它的组件的内容index这样就可以了,当然了这是它的一个默认内容,默认内容我们可以稍微的更改一下让它不至于文本太长,已经定义好了。当然这个样子不是我们想要的样子,我们可以根据自己的实际需要进行修改这个组件 然后定义完了以后接下来怎么样把它用作占位组件,可以在这个地方再声明一个组件,ph它的路径是哪一个,这个地方可以写相对路径index,然后下面components 这就是我们刚才添加的组件,先把它在底下进行声明,声明完以后就可以在这个地方去使用了,用它作为一个占位组件去使用,现在我们可以测试一下它的表现

我们在这个地方选中懒注入占位组件测试,选择以后清一下编译缓存然后单击测试,我们可以看到这个地方,它一上来的时候它显示了我们组件的一个内容,我们这个组件里边现在的一个文本内容就是stopwatch_ph,它会先显示这样的一个文本,然后显示一段时间以后又消失了,这样的一个,然后这个很明显,我们再刷新一下,这个是占位组件的一个显示,但是它有时候我们测试的时候发现它真实组件,其实它的加载还不是特别的一个顺畅 现在可以了。现在是真实组件,可以进行交互了,但是我们组件现在 它是不是有问题,因为它单击以后没有工作,这个可能是我们组件的一个问题,我们可以看一下我们组件,当然我们是为了测试我们的占位组件,现在其实还可以换一个组件,在我们的主页里面配置文件里面

可以将这个给它改成stopwatch换成另外一个组件测试也是一样的,样式没有显示,可以清一下缓存,然后再进行一个测试,在我们全局的app.json里边,因为我们现在 我们组件它已经是一个分包了,其实我们还可以添加一个预加载,预加载也是可以的,我们可以添加预加载,例如在我们使用主页的时候对分包给它加一个预加载也是可以的,写法可以参照我们之前的这样的一个写法,现在我们使用默认编译我们再测一下,可以将我们的里边这个选项给它去掉,这个只是测试我们占位组件的一个表现,把它去掉我们再测一下,显示了,单击以后可以运行,但是这个停止它不是特别的灵敏 现在停止了,它有滞后,里边有一个打印。我们代码演示就到这里。


下面我们看实践二,使用封面页。

还有一种在产品设计上的非技术的优化首页加载性能的方法,我们可以创建一个空白的效果的这样的页面,这个页面什么也不干,它作为伪首页只放一个Logo和应用名称,这个页面的JS代码也很简单,只需要在onReady这个周期函数里面添加一句向真首页的一个跳转代码就可以了,它的作用是加载主包里边的所有的基础内容,包括类库、插件、自定义组件等等这些,加载完成以后,再跳转到真正的产品首页,这个封面页位于主包内,而真正的首页则移到另外的一个代码包index里面,需要在app.json配置文件里面添加一个root为index的一个分包设置,同时在preloadRule这个节点下面开启封面页对index包的一个分包预加载,这种优化方法特别适用于那些产品比较复杂、分包共用的基础库又比较大只能放在主包中的这样的一个产品小程序。接下来我们开始代码演示。

下面进行实践二的代码演示。

使用封面页这个技巧,首先我们要创建一个封面页,封闭页我们把它放在我们pages这个页面下面,在这个下面我们创建一个目录cover,当然了我们还可以采用另外的一种更方便的方式去创建它,怎么样去创建,我们只需要在我们app.json这个里面去添加一个页面地址 cover,然后是index,添加完成以后只需要刷新一下,刷新以后开发者工具它会自动地帮我们把这个页面里面的一些基础代码给补全,现在我们可以看到这个目录下面 这四个文件已经有了,接下来我们要实现它这个代码。

这个代码我们已经有实现好的了,我们直接把它拿出来用一下,在相应的示例目录下面,我们找到pages/cover这样的一个目录,这是它的一个源码,把这个给它拷贝一下同时找到我们这个目录,在这个地方做一个替换 ,替换完成以后我们看一下这个页面里面的一些代码,这个地方很简单,它里面就放了一个image 一个text,然后这个地方会有一些样式代码,json这个里面其实什么也没有,这个节点都是可以去掉,然后在这个地方,只有在onReady里面添加了一个跳转到首页,这是我们一个首页的地址,现在cover页已经写完了,写完以后接下来我们还需要将我们的原来的首页把给它先去掉,去掉以后在我们的分包设置里面要加一个新的分包,这个地方要写index,代表是主页的一个分包,然后是在pages这个里边要写我们的页面的路径了,这个路径简单一点,我们还是使用拷贝相对路径的一种方式,复制以后然后粘到这个地方,同时把这个给它修改一下,前面的这些给它去了,这个也需要去掉,这个路径放在这个地方的时候前面不需要加index了,它跟我们原来在这个地方使用有一点点的不同,分包设置完以后,为了让我们主包主页面所在的分包加载更加顺利,我们还可以再添加一个分包预加载的规则,将这个放在这个地方,前面是index,然后放在这里,这个不太对,应该是用我们封面页的地址放在这里,也就是访问这个页面的时候要启动对另外的一个分包的一个加载,我们这个地方写index,它代表的是加载这个页面、访问这个页面的时候预加载这个页面,加快它的一个加载与渲染这样一种方式,这个封面页现在我们已经写完了,我们单击编译看一下它的一个运行效果。

这是封面页的效果,它会再跳到首页,在我们首页里边,我们前面不是用了占位组件对不对,这个地方我们还自定义了一个占位组件,其实如果我们这个组件它比较简单的话,另外再定义一个自定义组件给真实的组件用作占位组件的话,这个代价是非常大的,所以一般情况下我们不这么做,就用view就可以了,用标准组件view代替它,至于我们原来的组件其实可以不使用它 可以删掉了,不需要 这样就可以了,等它加载完成以后才可以使用,这样就行了,在加载完成之前用view进行一个优惠倒计时的一个显示就行了,这样就可以了。它有时候组件不会显示,这个时候我们清一下编译缓存 可以再测试一下。


最后我们总结一下,项目在分包以后代码包有三类:主包、普通分包和独立分包。主包它也是一个分包,但它不需要在app.json配置文件里边显式定义所有其他分包,没有瓜分的目录以及这些文件默认都会归在主包下面,并且它还有一个特殊的代码包名称,也就是__APP__,非独立的分包是可以依赖主包的,也就是说非独立分包中的页面被访问的时候主包同时也会被下载,但其他普通分包不会被连带下载,并且普通分包之间的组件和JS代码是不能直接相互引用和使用的,为了破除限制,小程序它提供了一种分包异步化机制,允许在一个普通分包里面异步加载和使用另一个普通分包里边的代码和组件。

还有就是加载的过程它是异步的,它不会影响当前这个页面的正常的一个渲染流程,主页在任何情况下都应该想尽办法被用户首先看到并且是尽快看到,任何情况下都不应该将白屏展现给用户,为了达到最快展现首页这样的一个目的,我们还可以将首页以外的所有的页面,包括主页上用到的自定义组件全部都放在分包里面,结合占位组件和组件的分包异步化的技巧最大化加快主页的渲染,如果首页它实在内容太多、用户中低端机的比例又比较大,实在是不好优化,这种情况下,我们还可以采用封面化的一个优化方案,让一个伪首页给真正的首页打前站。这节课我们就讲到这里,这节课我们涉及到的这些文档如我们屏幕上所示。

点击查看开放文档:


这节课我们主要学习了组件的分包异步化,学习了如何编写占位组件以及如何在page.json配置文件里面配置占位组件,还有如何在首页里边使用占位组件进一步优化首页的加载速度以及封面化的一个优化技巧,在使用封面化技巧的时候甚至还可以在伪首页先加载真首页需要用到的一个动态数据,然后通过一个页面间的事件通道对象也就是EventChannel,通过它将加载后的数据传递给真主页,这也是一种优化策略。下节课我们学习JS代码的分包异步化。

最后我们看一下思考题。这里有个问题请你思考一下,小程序分包以后,有些JS代码在这个代码包A里面它有用到,在另外的一个代码包B里面也有用到,那么这些共用的这些JS代码我们应该放在哪里,应该放在这个代码包A里面吗?还是放在B里面?如果两个代码包都放一份,显然这是一种浪费。如果放在主包里面,主包又不需要它,对主包的加载也是一个负担,况且独立分包它并不加载主包,你放在主包里边的共享代码,在独立分包里边也是无法直接使用的,难道在小程序里面就没有一种办法在这个代码包B没有加载成功的一个情况下,在这个代码包A里面就能加载和使用这个代码包B里面的某些代码吗?这个问题先留给你思考一下,下节课我们一起深入探讨一下这个问题。

最后一次编辑于  2022-07-14
赞 8
收藏

7 个评论

  • 随风
    随风
    2023-11-15

    uniapp可以使用占位组件吗?


    2023-11-15
    赞同 1
    回复 1
    • 随风
      随风
      2023-12-26
      uniapp暂时没提供占位组件,需要添加打包plugin自行处理
      2023-12-26
      回复
  • Frank
    Frank
    2022-06-30

    打卡打卡,占位组建,封面页策略

    2022-06-30
    赞同 1
    回复
  • 噜啦嘞
    噜啦嘞
    2023-10-13

    所以使用封面页后,首页这些页面就不能是tabbar页面了吗?然后自定义tabbar栏也无法使用了是吗?得自己写一个tabbar的组件

    2023-10-13
    赞同
    回复
  • 很好
    很好
    2023-05-10

    nice

    2023-05-10
    赞同
    回复
  • 箱子先生
    箱子先生
    2023-04-14

    不是封面页,使用wx:if判断如果数据加载完成,就显示页面内容,否则就显示一个logo,这样能缩短冷启动耗时吗?

    2023-04-14
    赞同
    回复
  • 清蒸鱼
    清蒸鱼
    2022-10-31

    -封面页这个方式,是不是不如直接给首页一个loading动画呢

    2022-10-31
    赞同
    回复
  • 开着邻居家的toyota追着日落
    开着邻居家的toyota追着日落
    2022-08-14

    想问下dalao,封面页与首页加骨架屏,有啥区别

    2022-08-14
    赞同
    回复 1
    • 清蒸鱼
      清蒸鱼
      2022-10-31
      骨架屏是会产生更多内容的
      2022-10-31
      回复
登录 后发表内容

小程序性能优化实践

课程标签