- 小程序性能优化实践
小程序性能优化课程基于实际开发场景,由资深开发者分享小程序性能优化的各项能力及应用实践,提升小程序性能表现,满足用户体验。
10-09 - 使用独立分包和分包预下载(上)
[视频] 你好,我是李艺。 上节课我们学习了按需注入和初始渲染缓存,明确了静态导航页适合使用初始渲染缓存,动态详情页适合使用骨架屏的策略。这节课我们学习分包、独立分包以及分包预下载。 首先我们看一下问题,在冷启动流程中间使用按需注入改良的只是代码注入阶段的性能,如果这个代码包本身它就比较大,那么在第一阶段,也就是资源准备阶段,就会浪费大量的时间,还有如果是代码包过大,它主包超过2MB,在微信开发者工具里面根本也没有办法上传以申请这个版本的审核,为了让这个代码包瘦身,微信开发者工具提供了静态代码依赖分析这个工具,可以帮助开发者找到无依赖文件。 但是有一点我们需要注意,有一些文件它表面上看起来是用不到的,但其实是不能删除的,因为有时候它是在运行时动态加载并使用的,如果这个代码包删除了无依赖的文件以后依然超过了2MB的限制,这时候应该怎么办?小程序又提供了分包以及独立分包的机制,只要单个代码包不超过2MB,总包大小不超过20MB即可。有些开发者可能觉得2MB限制太小了,决定阈值的从来其实都不是规定,而是网络环境和用户群体,国内有很多网民还在使用低端机,包括WiFi以及4G网络环境其实还没有100%的普及,或许等以后5G技术普及以后,限制会进一步的放开,那个时候主包大小或许会进一步的放大,在目前这个阶段,在当下网络环境里面如果要想提升小程序的启动性能以及运行性能,只能在深谙小程序的运行机制以及启动流程的前提之下,在已有的技术框架之下靠精耕细作的精神一个字节 一个字节地去优化。 接下来我们看项目实践。 目前我们的项目已经超过了2MB,必须通过分包分割总代码包的大小。 首先我们看实践一:用户主页分包、创建tab-bar组件。 将用户主页放在分包内,只需要给页面所在的目录添加分包配置就可以了,在app.json全局配置文件里面,我们可以在subpackages这个节点之下添加一个分包设置,root设置为当前页面所在的目录的一个名称,然后再加上pages设置就可以完成用户主页的一个分包设置了。 在小程序里面,如果是使用配置的方式开启tabBar导航,或者是使用这种官方自定义的方式,也就是我们通过在配置文件里面设置tabBar.custom等于true这样的方式实现tabBar导航组件,这个时候tabBar它页面地址只能放在主包里面,为了破除这个限制,我们可以使用自定义的方式实现tabBar的导航。 首先我们需要在app.json配置文件里面将tabBar的配置删掉,我们现在不需要这个配置了,然后我们在components目录下面创建一个tabBar的组件,用它提供全局的导航功能,在组件的JS代码里面会创建一个select方法,它设置哪个链接,当前是选中的状态,这个方法是给外部的代码进行提供的,这个组件的wxml代码很简单,主要是渲染一个list列表,而且这个list的数据还是从原来app.json文件里面复用过来的,wxss样式仅包含自定义组件本身它所需要的样式,这个里边有一个特殊的类样式,就是bar__active。这个是选中的样式,当这个链接与当前这个页面地址一致的时候这个文本它会呈现红色,这个图标也是红色图标,文本的选中颜色还有文本的默认颜色也就是它默认呈现的颜色,与我们原来在app.json配置文件里面的设置是一致的,完全以自定义组件这种方式实现的tabBar导航有哪些优点?我们一起看一下。 首先第一点,页面不再受分包的限制。我们可以将这个页面放到任何一个分包里面去;第二点就是tab-bar组件里边用到的图标,也不再被限制只能放在本地;第三点就是这个代码里面所有的tabBar页面的跳转也不用再单独使用wx.switchTab这样的接口,可以统一使用wx.navigateTo或者是wx.redirectTo这两个接口任何一个都可以,甚至tab-bar组件本身,如果我们愿意的话还可以将它进一步的优化,不放在主包里边,放在分包里面也是可以的。 现在我们开始实践一的代码演示。 在拿到这个源码以后,我们需要在小程序里面进行一个代码的引入,引入方式也很简单,只需要找到对应的目录然后选择,选择以后这个地方AppID要选择我们自己的账号的AppID,这个名称也可以修改,然后单击确定就可以了。我们要实现分包,实现用户主页的一个分包,首先我们看一下app.json这个文件,这个文件里面,目前我们这个地方其实已经有了一个分包设置了,在subpackages下面只需要在这个底下再添加一个新的配置就可以了。这个里面第一个字段要写的是root,它代表的是我们分包的一个地址,这个地方我们写user,因为我们这个项目底下确实有一个user的目录,也就是这个,根目录指定以后,接下来我们要指定pages,也就是这个页面了,这个页面它是我们在分包下面的一个相对地址,我们可以在这个地方复制一个相对路径,然后粘到这个地方,前面这些是不需要的,它只需要从pages下面,也就是从我们目录下面,开始计算路径,这样的话我们分包的一个设置就算是已经完成了。 再往下我们再创建我们的自定义导航按钮,自定义导航的组件在我们的components目录下面,然后去创建这个组件,现在这个目录还没有,可以创建一下目录,然后这个目录下面再创建一个tab_bar这样的子目录,在这个目录下面放tab-bar自定义组件它的一个源码,可以采用一种快速的新建的方式,比如这个地方我们选择新建Component选择这个菜单,然后写入一个index,完成以后,下面所有的四个文件已经全部默认帮我们创建了,下面开始实现这个代码,这个代码我们之前这已经有实现好的,为了快速我们直接复用我们已经实现的代码,这是页面的标签代码,这个标签代码里面我们可以看一下,主要是一个列表渲染,这个地方用了一个wx:for这样一个列表渲染,然后循环渲染这个list里边还有关于image这个地方有一个判断,当前的index是否等于selected就是我们当前选择的索引,如果等于的话,然后去渲染这样的一个图标地址,如果否的话就是选择另外一个图标地址,这是它的样式。 这个地方是我们这个页面的就是文本 一个标题或者说我们页面的一个名称,这个页面的一个跳转是靠我们绑定的一个事件,在这个上面可以看一下,在这个地方有一个tap 一个绑定,nav的方法上面,我们再看一下JS代码,这是我们JS代码,这个JS代码里面nav,这是我们刚才提到的用于页面跳转的一个方法,上面这有一个select它的参数是index就是索引,我们当前选择哪一个,这个方法是对外提供的,在这个页面里面使用这个组件的时候,稍后我们会调用这个方法。 再往上就是data对象了,第一个是一个selected,就是选择的索引,我们当前选择这列表里面哪一项作为选中的页面,它的默认是0,下面这个list这些数据是我们原来的app.json里面的数据,它的一个修改,我们可以看一下我们原来的数据这个地方 这有一个list,我们可以将这个list给它拷贝一下,除了这个list还有两个color,这里有一个color 这有一个color,我们先将这个list给它拷贝一下,然后到tab_bar这个里面,可以放在这个地方对比一下,这两个数据是很像的,它的差别其实只是我们pagePath前面多了一个斜杠,包括iconPath还有selectedIconPath前面多了两个斜杠,其他的其实都是一样的。 当然了我们上面的这种格式是微信它定义的,在app.json里面,如果是要定义tabBar导航的话必须要用这种格式,但下面这种格式是我们自定义的,我们选择这样一种方式定义便于我们和默认的官方配置、保持一致的数据结构,最后我们再看一下样式。这个代码里面只有一项就是component等于true,如果它是个组件的话,在这个json里边它这一项是等于true的样式代码,这是它的一个样式代码,在样式代码里面可以看到这个里面有一个bar__active代表的是选中状态,选中状态下它文本色,这个地方其实是文本,我们可以看到在这个里边这是它的样式,选中以后文本变成这个颜色,d81e06这样的一个样式与我们前面在这个地方看到的样式它俩是一样的,包括我们前面的5151默认的文本颜色跟我们组件里面的样式也是一样的。我们可以看一下,也就是这个颜色,这是它默认的一个颜色,是一样的。这是组件已经准备好了,这个它默认生成的,其实下面那个我们不需要,只需要这一个就可以了,组件已经准备好了。 接下来我们需要在配置文件里面做一个组件的引入,在这个里面也需要写一个usingComponents,然后是tab-bar,一般的话自定义组件的命名方式就使用这样一种单词中间用连字符,因为官方它组件,然后分割单词也是这样一种形式,所以我们就沿用官方的形式就可以了,组件的地址在哪里,这个地方可以复制一下相对地址,然后粘到这个地方再稍做修改这样就可以了,稍做修改,当然后面JS不需要 把这个给去掉,接下来我们就需要在我们的三个页面:用户主页、商品详情页和主页面里面分别添加tar-bar组件的一个使用。 首先我们在user这个里面找到这个标签页wxml这个页面,在它的最下方添加一个tab-bar,再给它一个id,这样一个代码,然后我们还需要在JS里面,在这个页面的onReady的时候onReady,这个地方没有onReady就在这个地方再加一个onReady,在这个地方需要调用这个页面的selectComponent这个地方的参数,我们写#tabBar 井号代表的是id,tabBar是我们刚才定义的id,选择以后再调用它的select方法,要传一个参数,因为我们用户主页居于导航栏的里面的属于它的索引在2这个位置,所以我们这地方要选2。这是用户主页,然后将这个代码复制一下,在另外的两个页面里面,一个是商品详情页,在这个页面最下方也拷贝一份,还有是我们的index主页的最下方也放置一份,这是wxml代码,接着是拷贝我们的选择代码,在主页里面找到onReady,在这个地方可以放在最后面 放在这个位置,这个是主页,数字要设置为1,还有一个是商品详情页,商品详情页在onReady里边添加代码,这个要设置为0,这就是我们的代码,现在已经改造完成了。 单击编译我们看一下运行效果。这个地方有一个问题,就是我们的地址它不应该在subPackages分包内出现这样的一个提示,这个提示是什么意思,看一下我们这个项目的配置文件,现在我们给用户主页实现分包,将这个地址放在了这个地方,当然这个地方多了一个.js,放在这个地方以后,在我们整个文件默认的pages下面,这个地址其实我们就应该给它删掉,它不需要了,一个页面不能同时出现在两个包里,然后这样去处理再编译一下 看看效果。 这个地方也有一个问题,模拟器无法获取这个文件,已经被忽略上传,它这个忽略上传我们暂时不要去理它,只是它自己的一个提示,现在要测试导航组件的一个表现是否正常,选择商品页,商品页现在高亮了对吧,然后选择主页,然后主页高亮了对吧,然后选择我的页面,我的页面也高亮了对吧。这个导航已经实现了它预想的一个功能,现在我们拿我们的商品详情页,就是detail这个页面它作为启动页再测试一下,也没有问题对吧,也显示了这个代码它的作用是良好的。 在这个地方有一点我们需要提示一下,我们这个代码里面是有选择组件,然后再调用其中的方法的代码也就是这个对吧,在主页里面这个地方选择组件然后再调用它的方法,选择这个组件它其实未必是可以选到的,所以如果这个地方我们要避免出错的话我们可以加一个问号,加个问号以后 就是ES6里面的可选链语法,如果是它不是null,然后找到这个组件,调用它的一个方法,这样的一个语法,这是主页,然后在这个商品详情页里面也是一样的一个处理,这个地方加一个问号,还有一个是在用户主页这个地方也加一个,我们再测试一下,没有问题。正常情况下这个页面已经走到了onReady这个地方,按理说它不会出现选择不到的这种情况,但是有一种情况我们稍后可能会遇到,如果是我们当前这个页面,它本身它跟我们的用到的组件,我们现在这个组件tab-bar这个组件是放在我们主包里面,因为它是在app.json里面配置的,如果是我们这个页面是在一个独立分包里面 它是独立的,然后它显示的时候其实主包没有加载,主包里边的组件你也使用不了,这种情况下有可能,这个地方我们要去选择组件的时候,它可能拿到的是一个空值或者是一个undefined,你在一个undefined调用它的方法,显然是不合适的话可能会报错,所以这个地方所有的组件其实都是一样,你如果想万无一失的话,给它加一个问号,这个问题就可以轻松化解了。 这个代码演示就到这里了。
2022-07-14