减少主包体积

为何要减少主包体积

从前文小程序的启动流程得知,在打开小程序的页面时会经过【下载小程序包】、【加载主包资源】、【执行页面逻辑】等过程,如果主包中内容较多,会影响【下载小程序包】和【加载主包资源】的时长,页面展示就会变慢,fmp 也会升高。在性能优化中,我们需要找到各种办法降低fmp。

主包里都包含什么内容

我们先来看看小程序的编译逻辑:

来源内容编译后去向
主包.swan / .js / .css / .json主包
分包.swan / .js / .css / .json分包
自定义组件.swan / .js / .css / .json主包
公共资源中.js整个项目中,引用次数大于1的文件编译在 主包 中,其他在分包中
.css编译到引用的各个页面中,编译后当前css内容的体积会成倍增长
图片 / .json主包
npm包服务组件 / 插件 / 动态库主包
utils方法整个项目中,引用次数大于1的文件,编译在 主包 中,其他在分包中
模板如果模板被开发者放入主包中,编译后就在主包中;如果放入分包中,编译后就在分包中

从上表中的编译逻辑可以分析出:

  • 自定义组件(插件、动态库等)编译时都会打包到主包中,目前还不支持依赖分析,这些内容的体积会影响主包大小
  • 公共资源中的图片在编译时无法进行依赖分析,所以会直接划分到主包中

减少主包体积的方式

方式1:减少主包中包含的页面

思考1:主包中应该包含什么内容呢?

首先按官网规定,app.json - tabBar 中设置的页面,是必须要放在主包中的,其次重点页面也需要放在主包中。从 fmp 计算方式可知,我们需要知道小程序中哪些是入口页面。这方面的信息,从开发者平台的数据中可以查到。在开发者平台找到目标小程序的【数据分析-行为分析】,我们可以按入口页次数排序,找到访问量大的页面,这些就是需要放在主包中的页面。

减少主包体积 - 图1

需要注意的是,如果小程序入口较为分散,则需要计算出多少个页面对小程序整体 fmp 有较大影响。

思考2:如何在不影响外部推广的情况下,剔除主包中的部分页面?

如果主包中已经包括了很多不重要的页面,且不确定是否有外部推广,不敢随意改动真是路径,我们可以选择通过自定义路由来映射 path 与真实页面路径,从而在不影响外部推广的前提下,把这部分页面从主包中划分出去,减少主包体积。
以某政务小程序为例,主包中的页面从访问量小的开始算,从主包中使用自定义路由移除48个页面,fmp提升了5%左右。在使用自定义路由后,项目上线时需要注意小程序基础库版本的升级

注意:

  • 自定义路由虽然可以让我们很方便的分包,但过多的自定义路由配置,会增加小程序初始化时长,从而增加整体 fmp 时长。所以自定义路由在必须配置的前提下,越少越好。以某政务小程序为例,增加50个自定义路由配置后,fmp 增加了15ms。
  • app.json中在设置 app.json - preloadRule 时,key值并没有用处,所以增加路由后,key 值写成 path 还是真实路径都可以,小程序框架框架中只会读取 value 值。

减少主包体积 - 图2

思考3:主包中的内容是越少越好么?

这就要结合小程序的主包、分包下载机制来看,如果页面在分包中的话,打开页面时会同时需要下载主包和分包。

入口下载内容
入口为主包页面主包
入口为分包a中的页面主包、分包a

思考4:其他的页面分成几个子包合适?

这要从小程序并行下载子包数量、包体积与下载失败率的关系、分包页面与主包页面紧密程度、页面入口 pv 等几个方面来综合衡量。

1、【并行下载子包数量】

小程序双端并发下载数量较少,大概率都是串行下载,所以分包数量不宜过多。

2、【包体积与下载失败率】

双端下载失败率均在千分之几以内,按经验来说,如果待下载的内容在 1M 以下的体积,下载失败率可以忽略不计

3、【分包页面与主包页面紧密程度、页面入口pv】

这是个需要具体小程序具体分析的问题。以某政务小程序为例:

减少主包体积 - 图3

  • 某政务小程序小程序页面很多,首先我们分出了页面月总pv在500的以下,这些访问量很小的页面被分在 lower 分包中
  • 从开发者可查询到主包页面的跳转依赖的页面数据,这些依赖页面打在 mainDep 包中,其中刨除掉 lower 中已有的
  • lower 分包中的页面由于访问量很小,在 app.json - preloadRule 中设置需要下载的分包时,不设置 lower 分包
  • 综合考虑后某政务小程序分为 mainDep 和 lower 2个 分包

方式2:减少自定义组件

1、减少共用的自定义组件

根据编译逻辑可知,小程序中使用的所有自定义组件目前还无法按需加载,这些自定义组件暂时都会编译到主包中。由于分包页面都不是重点页面,只在分包中使用的自定义组件,可以考虑直接放在分包各页面的模板中,减少主包体积

2、减少非共用的自定义组件

只有一个页面使用的自定义组件,可以直接合并到页面模板中,减少初始化和创建自定义组件的损耗

方式3:优化公共资源

1、优化 fn.js 文件

减少主包体积 - 图4

fn.js 文件就是我们常说的公共资源或者 utils 中的 js 文件,根据编译逻辑可知,这种 js 文件如果被引用大于1次,就会编译到主包中。开发中往往我们的 fn.js 文件中,都会包含很多个方法,导致页面无法精确的引用,从而不能更精确的编译打包。建议每个方法写在一个文件中,方便更精准的编译打包。

2、优化公共资源中的 css

减少主包体积 - 图5

根据编译逻辑可知,公共资源中的 css 文件,被页面 css 文件引用后,编译时会自动合并到每个页面的 css 中。也就是说,公共资源中的css看起来是写了一份,但编译后会成倍复制,分别merge到引用的页面中,所以公共资源中的 css 只提取必要内容的即可。尽量减少引用公共资源中的 css 后,又在页面 css 中覆盖一遍的情况。

3、优化公共资源中的图片

根据编译逻辑可知,所有在非分包页面文件夹中的图片,都会被打到主包中。所以需要逐个对我们的图片做筛选,如果图片较大,可以选择放在 CDN 上,尽量减少主包体积。同时,压缩图片也是必不可少的。