滴滴出行小程序业务爆发式增长,如何应对包体积限制?

2024-06-02
来源:网络整理

背景

微信对于小程序包大小的要求是总大小不得超过 20M,主包和单个子包大小不得超过 2M。虽然支付宝计算小程序包大小的方法与微信略有不同,但整体计算方式差不多。

2018年至2019年初,滴滴出行小程序承载的业务只有网约车,业务需求较少,在主包中即可处理。下半年,为了将微信钱包/支付宝九宫格入口迁移到小程序,小程序开始增加公共交通/代驾/专车/单车/拼车等多项业务线,同时网约车的业务需求也需要全力补齐,业务量和代码量呈现爆发式增长。

滴滴出行囊括了种类繁多的出行服务,包括快车/私家车/出租车/豪车/拼车/单车/代驾/拼车/公交/车生活等众多业务线。整个滴滴出行小程序最重要、使用最频繁的页面就是首页和订单详情页。首页承载着各业务线的需求表达,各业务线的订单详情页承载着具体的出行订单展示逻辑。此外,还有个人中心、营销页、设置、历史行程等各类功能页面。

按照滴滴出行的产品逻辑,所有业务线的需求表达逻辑都承载在首页上,为了提供良好的切换体验,首页采用单页置顶引导方案展示业务线,即每条业务线在首页提供一个需求表达组件,当用户切换到置顶引导的业务线时,对应的业务线组件就切换出去。

在这样的设计下,所有业务线的需求表达逻辑都集中在单个首页上,导致承载首页的主包大小在业务迭代过程中迅速增大,很快触及小程序平台单个包2M的上限,给后续业务迭代开发带来巨大阻碍。因此控制包大小是我们在小程序开发过程中面临的一大难题。

音量控制

下面我们将介绍我们在滴滴出行小程序开发迭代过程中,针对其规模进行的一系列优化和控制实践。

▍基本优化方法

对于小程序来说,优化包大小的基本方法包括:资源压缩/去代码冗余/资源CDN/异步加载。

在 Web 开发中,提供了大量的代码优化能力,包括依赖分析、模块去重、代码压缩、树、侧边等,这些能力可以轻松完成资源压缩、去除代码冗余。滴滴出行小程序基于滴滴开源小程序框架 Mpx() 开发,Mpx 框架的编译构建完全基于并兼容内部生态,自然可以利用上述能力来优化包大小。

小程序支持使用CDN地址加载部分静态资源(如图片、视频),我们会尽量对相关资源进行压缩并放到CDN上,避免这些资源占用过多的包大小。

在小程序场景下,无法像 web 一样方便的通过标签进行异步加载,但后来小程序平台支持了分包加载的方案来实现该能力。由于分包加载是小程序独有的技术规范,无法直接支持,所以 Mpx 框架针对该技术规范做了很好的适配支持。关于该能力的应用,后面我们会详细阐述。

此外,Mpx框架针对小程序场景也做了大量包大小优化适配工作,比如尽可能减小框架占用的包大小(压缩后56Kb)、按需打包构建引用的页面/组件、声明通用样式以便样式复用、将通用模块抽取到子包中等等。

有了Mpx框架这些能力的支持,基本不需要任何额外的配置就可以构建一个初步优化的小程序包。

微信开发者工具中也有类似的选项“上传代码时自动压缩混淆”,可以勾选,但在开发者工具中上传代码时,体积是直接根据当前项目代码的体积来计算的,而不是压缩后的体积。因此,如果你使用原生小程序进行开发,你的代码很可能会进一步压缩以节省空间。

▍分析体积

虽然框架在体积控制上提供了很多优化,但是随着业务的迭代,我们发现主包体积还是比较大。

当我们遇到主包过大的时候,我们需要搞清楚主包里有些什么,为什么这么大?

使用原生小程序或者其他非基于框架进行开发的同学遇到这个问题可能只能看硬盘上的文件大小,这样各个模块的大小占比可能不太直观,我们可以借助类似这样的插件来辅助分析。

比如这是一个使用Mpx框架编写的demo,通过运行npm run --,可以看到这样的界面:

可以看出这个demo项目是由//-/core-js等第三方库组成的,各个库的大小以及相互的依赖关系也可以清晰的看到。

滴滴出行小程序也可以看到类似的图,可以看到整个项目是由哪些代码组成的。

此外,滴滴出行的前端开发一直采用“源码编译”,这样可以让整个项目中的公共依赖只共享一份,总之也有助于减少项目代码的大小。(相关信息:)

要完美发挥源码编译的效果,需要上下游共同努力,建立完整的源码编译生态。比如主项目的依赖方在声明公共依赖时,应该使用或者声明一些公共依赖。这些共享依赖应该在主项目中统一声明,避免因为版本不同而安装两个公共依赖,导致体积增大。由于滴滴出行小程序涉及业务线和团队较多,部分团队可能并不知情,因此上述降级场景可能确实会出现在代码中。根据分析图,可以很容易地发现这个问题,并推动相关团队移除这些重复的依赖。

同时我们根据体量分析图针对较大的文件进行了重点分析,进行了一轮业务代码梳理和精简,删除了一些无用的代码,精简了消息体描述文件。

▍配置分包

分包是小程序提供的一种类似网页异步导入的解决方案,可以将一些初始进入时不需要的页面放入分包中,只有跳转到相应页面时才会下载分包。将这些页面及其附带的资源放入分包中,可以有效减少主包的大小。

Mpx框架初期支持分包规范,资源访问规则与微信保持一致,根据资源存放的目录,将资源输出到主包或者子包,利用这个能力我们将行程页面移到了子包,节省了约200K空间。

在行程页面拆分成功之后,我们开始将所有非首页的代码进行分包,比如起点终点选择、个人中心等,由于有些业务线是通过npm访问的,我们也尽可能将这些业务线的非首页代码全部放到分包中。

滴滴开发招聘_小程序开发滴滴_滴滴旗下的小程序

这里再补充一下,得益于mpx早期设计的业务合并方案,业务可以独立开发,集成起来非常方便。后来发现微信的分包的JSON配置设计和mpx很相似,于是在此基础上支持了微信的分包,用户侧只需要在原有基础上增加一个名字来标记分包即可。

去掉各个分包之后,整个项目结构大致如下图所示:

初期分包工作完成后,共计约400K的空间从主包移到了分包。

▍分包资源精细化管理

上面提到,Mpx 框架初始的子包处理规则是完全按照微信的方式,将子包路径下的资源收进子包中。但由于 npm 管理的资源都在目录下,不属于任何子包路径,所以会全部收进主包中。

比如我们之前有一个trip page子包,trip page自身的状态管理都在trip page子包的路径下,所以会收集到trip page子包中。trip page还用到了打包好的didi-库,它是一个公共的npm包,即使只在trip page子包中使用,由于其自​​身的路径在下面,所以也会收集到主包中。

由于前期的一些设计,行程页和首页的资源是分开的,在各自的路径上相对独立存在,第一期分包的量主要还是行程页,这刚好契合了Mpx早期分包处理的特点,所以可以比较好地收集在行程页分包中。

随着业务的迭代,后续业务线会有大量通过npm来访问,会产生大量的npm包资源,它们都在目录下,所以会全部收集到主包中。

因此Mpx框架经历了一系列的变革:

这样,无论子包中引用的资源原本位于何处,最终输出时都会尽可能地输出到dist子包目录下,避免占用主包空间。

经过这样的改动之后,项目结构看上去和之前没有太大区别,但是得益于 Mpx 处理子包资源能力的升级,我们能够顺利的将业务线子包中引用的 npm 资源输出到其子包目录中。

▍封面设计

后来滴滴出行小程序需要取代微信/支付宝原有的入口,接入小程序的业务线迅速增加,包裹大小迅速增长。

这部分增长的主要原因前面已经提到过,所有的业务线都要打通首页来展示,这也是业务的特点使然,滴滴出行提供了丰富的出行产品线,包括快车/私家车/出租车/豪车/拼车/单车/代驾/网约车等产品,用户可能需要反复切换选择,这个过程还必须保留起始车型和结束车型等信息,必须是页面切换组件加上一整套非常复杂的大规模状态管理才能顺利实现。不像有些电商/资讯平台,不能把不同的功能拆分到不同的页面,让用户通过首页上的菜单进入子页面再操作,首页只承载了入口,业务逻辑较少,处理分包会容易很多。

所以每条业务线都要提供一个首页组件用于接入,这个组件会在首页上使用,所以无论如何也不能分包,最终整个首页主包的体积可以分为两部分:基础库和业务代码,两者体积比为:公共依赖基础库约1M,业务代码约1M。

基础库数量如此庞大,主要是因为滴滴出行的业务线、业务团队众多,各方都有自己的一些基础依赖。比如网约车依赖长链路通信 pb 数据描述文件、地图依赖大数据计算库、拼车依赖 CML 框架运行时、代驾依赖通信网关库,还有公共组件库等等。

所以滴滴出行小程序面临的问题,已经无法通过当时纯技术方案在短期内快速解决,所以我们做了一个工程架构的调整,可以称之为封面方案,来解决主包的问题。

简单来说,封面计划就是做一个封面,以滴滴出行的logo作为启动页,这个页面加载完成后,会立刻跳转到另外一个页面,这个页面其实就是承载业务的,放在分包里面。

这样操作的意义在于,主包中只包含了各方依赖的基础框架/库,而所有业务都提取到了子合约中。

这是封面设计完成后的项目结构图,首页业务逻辑很大一部分已经提取到首页分包中。

这样迁移的结果是,我们可以有 2M 的主包空间来存放基础公共库,还有 2M 的子包来存放前面提到的整合各项业务的滴滴出行“首页”。当时主包大概有 1.2M,业务的主子包有 800K+。

这次改造最棒的地方在于后续业务迭代带来的体积增长几乎全部在主业务子包中,剩余的 1.1M+ 空间依然足够业务迭代使用。理想情况下主包体积可以长期保持不变,因此主包不会因为业务需求的不断发展而超限,完全不用担心主包体积问题。

当然可以看到,这个方案本身并没有减小什么体积,只是改变了位置而已。另外这个封面页方案其实也存在一些缺陷,比如首屏业务的展示会因为需要加载的内容较多而比较慢,不过小程序本身有不错的资源缓存能力,所以可以接受。

相比于体量阻碍需求迭代、阻碍产品线接入的问题,这个方案至少能解决有没有问题。我们的开发团队也会持续跟进体量问题,看看产品方案是否会有变化或者小程序本身会不会提供一些解决方案来进一步优化这部分。

总结

Mpx框架在包大小控制上做了大量工作,对npm场景下小程序分包提供了非常完善的支持。

在框架支撑的基础上,滴滴出行小程序团队通过梳理业务依赖,充分利用分包、调整交互方案等手段,将庞大复杂的滴滴出行小程序包体积控制在平台限制之内,不妨碍业务开展。

希望本文能给遇到包大小问题的小程序开发者带来一些启发,欢迎留言交流。

头像:

分享