在19年下半年,为了将微信钱包/支付宝九宫格入口的滴滴出行迁移为小程序,团队对小程序进行了大量的功能升级与补全。在整个过程中也遇到并克服了一系列问题和挑战,其中包体积问题尤为突出。接下来全面介绍一下滴滴出行小程序在体积控制方面做的努力与沉淀。

1. 

背景

微信对小程序包体积的要求是总体积不得超过20M,主包及单个分包体积不得超过2M。支付宝对于小程序包体积的计算方式虽和微信略有区别,不过整体也大同小异。

18年至19年初时,滴滴出行小程序里承载的业务只有网约车,且业务需求较少,在主包内都能够搞定。而在下半年时,为了将微信钱包/支付宝九宫格入口迁移至小程序,小程序开始新增诸如公交/代驾/车服/单车/顺风车等众多业务线,同时网约车的业务需求也要做全面的补齐,业务量和代码量一起爆炸式增长。

滴滴出行包含了丰富多样的出行业务,包含了快车/专车/出租车/豪华车/拼车/单车/代驾/顺风车/公交/车生活等众多业务线。整个滴滴出行小程序的最重要,使用最高频的页面是首页与订单详情页,首页中承载了各个业务线的需求表达,各个业务线的订单详情页则承载了具体的出行订单展示逻辑。此外还有各种功能页面比如个人中心,营销页面,设置,历史行程。

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

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

2. 

体积控制

下面我们将介绍滴滴出行小程序开发迭代过程中,我们对于小程序包体积进行的一系列优化控制实践。

基础优化手段

对于小程序来说,基础的包体积优化手段包括:资源压缩/去除代码冗余/资源CDN化/异步加载。

在web开发中,webpack提供了大量的代码优化能力,包括依赖分析、模块去重、代码压缩、tree shaking、side effects等,这些能力可以方便地完成资源压缩和去除代码冗余的工作。滴滴出行小程序基于滴滴开源的小程序框架Mpx( https://github.com/didi/mpx )进行开发,Mpx框架的编译构建完全基于webpack,兼容webpack内部生态,天然可以使用上述能力对包体积进行优化。

小程序中支持部分静态资源(如图像视频等)使用CDN地址加载,我们会尽可能将相关的资源压缩后放到CDN上,避免这部分资源对包体积的占用。

小程序场景下无法像web当中通过script标签便捷地进行异步加载,但是小程序平台后期纷纷支持了分包加载的方案来实现该能力,由于分包加载是小程序特有的技术规范,webpack无法直接支持,因此Mpx框架专门针对该技术规范进行了良好的适配支持,关于该能力的应用我们会在后文详细阐述。

除此之外,Mpx框架还针对小程序场景进行了许多包体积优化的适配工作,如尽可能减少框架运行时包体积占用(压缩后占用56Kb),对引用到的页面/组件按需进行打包构建,声明公共样式进行样式复用,分包内公共模块抽取等。

在Mpx框架的这些能力的支持下,基本不需要额外配置就能构建出一个经过初步优化的小程序包。

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

分析体积

虽然框架已经提供了很多在体积控制方面的优化,但是随着业务迭代我们发现主包体积依然偏大。

在遇到主包体积偏大后,我们需要弄明白,主包里有哪些东西?它们为什么这么大?

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

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

可以看到这个demo工程由 moment / lodash / socket-weapp / core-js 等第三方库组成。各个库的大小,相互依赖关系也能清晰地看出。

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

另外,滴滴出行前端开发一直是采用“源码编译”的,可以让整个项目里公共的依赖可以实现仅有一份,一起共用。简而言之,也有助于减少项目代码体积。(相关资料:https://github.com/DDFE/DDFE-blog/issues/23)

要完美发挥源码编译的效果,需要上下游一起建立整套源码编译生态,比如主项目的依赖方在声明公用依赖时,就应该用peerDep或者devDep来声明一些公有依赖,这些共有依赖应该在主项目中统一声明,避免因版本不同装出两份公共依赖,那样反而会增大体积。由于滴滴出行小程序涉及业务线及团队众多,部分团队可能并不知道这个事情,因此代码里实际是可能出现上述劣化场景。而依照分析图,可以容易地发现这种问题,并推动相关团队清除这些重复依赖。

同时,我们依照体积分析图,对其中体积较大的文件重点分析,进行了一轮业务代码梳理和精简,删除了一些无用代码,精简了websocket的消息体描述文件等。

配置分包

分包是小程序给出的类似web异步引入的一个方案,把一些初始进入时不需要的页面可以放进分包里,跳转到对应页面时才去下载分包,将这些页面及其附属资源放到分包里可以有效减少主包体积。

Mpx框架早期对分包规范进行了初步支持,资源访问规则保持和微信一致,主要根据资源存放的目录判断应该输出到主包还是分包。有这个能力后,我们把行程页抽到了分包,大概抽出了200多K左右的空间。

有了行程页的成功拆分后,我们开始对所有的非首页代码进行分包操作,比如起终点选择和个人中心。以及部分业务线的接入是通过npm的方式接入,我们也尽可能将这些业务线的所有非首页的代码放到了分包。

这里还有个题外话,得益于mpx早期设计了packages形式的业务组合方案,可以很方便地让业务独立开发,又能及其方便地整合。而后发现微信的分包的json配置设计和packages很像,就在这个基础上支持了微信的分包,用户侧仅需在原来的packages基础上加一个query标记这个分包的名字即可。

拆除各个分包后,整个项目结构大概如图:

初阶的分包工作进行完毕后,总计从主包里拆了差不多400K的空间到分包里。

分包资源精细化管理

上面提到,Mpx框架初期的分包处理规则是完全按照微信的方式,把在分包路径下的资源收集到分包里。而npm管理的资源因为都在node_modules目录下,不属于任何分包路径,则会被全部收集进主包。

比如之前我们有行程页分包,行程页自有的状态管理store整个都在行程页分包的路径下,就会被收集到行程页分包中。而行程页还用到了封装好的didi-socket库,这个库是公共的npm包,即使它只在行程页分包里被使用,但由于它本身路径是在node_modules下的,那么就会将其收集进主包里。

因为早期的一些设计,行程页的资源和首页是分割开的,都比较独立地存在于各自的路径下,一期的分包处理的大头也主要是行程页,它刚好契合了Mpx初期对分包处理上的特点,因此能较好地收集进行程页分包里。

随着业务迭代,后续大量业务线的接入都是通过npm进行的,就会有大量npm包资源,他们都在node_modules目录下,因此全部会被收集进主包。

所以Mpx框架进行了一系列改造:

  • 在构建的依赖收集过程中,我们会对收集到的依赖打上标记,记录它是被哪些分包引入的。一旦它只有一个分包引入,它就会被输出到这个分包中。

  • 我们会根据用户定义的分包配置,自动在 SplitChunksPlugin 中生成各个分包的 cacheGroups ,把分包中的复用模块抽取到分包下的bundle中。

  • 对于组件和静态资源,如果他们被多个分包所引用且未在主包中引用,为了确保主包体积最优,这些资源将产生多份副本分别输出到对应分包中,而不会占用主包体积。

这样一来,不管分包中引用的资源原本在什么位置,最终输出时都会尽可能将其输出到dist的分包目录下,避免占用主包空间。

这个改动完成后项目结构看似和之前一样,但得益于Mpx处理分包资源能力的升级,我们得以将业务线分包中引用的npm资源成功输出到其所在的分包目录下。

封面方案

再后来滴滴出行小程序需要替换微信/支付宝里原有的WebApp入口,小程序接入的业务线迅速增加,包体积迅速增长。

这个部分体积增长的主要原因前面提到过,所有的业务线都要接入到主页来展示。这也是由于业务特点决定的,滴滴出行提供了丰富的出行产品线,包括快车/专车/出租车/豪华车/拼车/单车/代驾/顺风行车等产品,用户是可能需要反复切换挑选的。这个过程还要保留起终点车型之类的信息,必须是一个页面内切换组件加一整套非常复杂的大型状态管理才能比较流畅顺滑地实现。而不能像一些电商/信息平台,将不同的功能拆分到不同页面,让用户通过首页的菜单进入子页面再进行操作,首页只承载入口,只有较少的业务逻辑,分包处理起来就会容易很多。

因此各个业务线都要提供首页组件进行接入。这个组件会在首页被用到,所以无论如何也拆不到分包里。最终,整个首页主包部分的体积可以分成两个部分:基础库和业务代码。两者的体积占比大概是公共依赖基础库占1M左右,业务代码占1M左右。

这么庞大的基础库体积主要是由于滴滴出行的业务线及业务团队众多,各方均有一些自己的基础依赖。比如网约车依赖的长链接通信pb数据描述文件,地图会依的大数计算库,顺风车依赖的CML框架运行时、代驾依赖的通信网关库,以及公用的组件库和polyfill等。

所以滴滴出行小程序面对的问题在当时已经无法用纯技术方案在短期内快速解决问题了,于是我们做了一个工程架构调整,可以叫封面页方案,解决了主包问题。

封面方案简单讲,就是做一个带滴滴出行Logo的封面作为启动页面,而页面一旦加载,立刻跳转另一个页面,这个页面真正承载业务,且它被放在分包里。

这个操作的意义在于,主包里就只剩下了所有方都要依赖的基础框架/库等,而业务全被抽离到了分包里。

这是封面方案完成后项目的结构图,之前很大块的首页业务逻辑被抽出到首页分包中了。

这样一个挪移的操作的结果是我们可以有2M的主包空间来乘放基础的公共的库,有一个2M左右的分包来乘放前面提到的滴滴出行的集成了各种业务的“大主页”。而当时拆下来差不多有1.2M的主包,800K+的业务主分包。

这个改造最优秀的一点在于,后续的业务迭代产生的体积增长几乎全是在业务主分包里,剩下的1.1M+空间留给业务迭代还是比较充裕的。而主包的体积在理想条件下是可以长久保持不变的,就不会因为业务需求的不断开发反复导致主包体积临近超标,不再需要为主包体积感到焦虑。

当然,可以看到,这个方案本身是没有消减任何体积的,只是把位置变换了一下。除此之外,这个封面页方案其实也存在一些缺陷,比如首屏业务的展示会变慢,因为要加载的内容会变多,不过小程序本身有较好的缓存资源的能力,因此还算可以接受。

相比于因体积问题卡住需求迭代以及产品线的接入,目前这个方案至少能解决有无问题。我们开发团队后续也会持续跟进关注体积问题,看是否会有产品方案变更或者小程序本身给出一些解决方案来进一步优化这个部分。

3. 

总结

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

滴滴出行小程序团队在框架支持的基础上,通过梳理业务依赖,充分利用分包,调整交互方案等一系列手段,在不阻碍业务发展的前提下,将庞大复杂的滴滴出行小程序包体积控制在平台限制范围内。

滴滴出行小程序体积优化实践相关推荐

  1. 京东快递小程序分包优化实践

    前言- 随着项目规模增大,小程序分包优化是必须要面对的问题.分包不合理,不仅影响项目迭代和上线计划,还关乎用户体验,甚至因此导致 C 端用户流失.本文主要介绍京东快递小程序分包过程中踩过的坑,以及小程 ...

  2. 小程序体积优化(1)--优化大文本

    缘起 昨天接手了一个小程序,让新增一些页面.页面写完,预览失败.为啥?大小超过2M了.虽然说小程序目前支持分包的方式让上限提高到4M,但是考虑到业务的发展,还是先优化一波. 去掉无用数据 优化体积,从 ...

  3. 基于mpvue的仿滴滴出行小程序

    初衷 本人最近一直在研究小程序,一个偶然的机会发现了mpvue框架,刚好本人对vue十分喜爱,就决定入坑了.曾经在掘金看过一个仿旧版滴滴的小程序,感觉挺不错的,但它是基于原生小程序的,所以就决定花了一 ...

  4. 美团扫码付小程序的优化实践

    短短几年的时间,微信小程序已经从一颗小小的萌芽成长为参天大树,形成了较大规模的开发者生态系统,尤其是在支付.线下垂直领域潜力巨大. 作为领先的生活服务平台,美团的技术团队在小程序领域也进行了很多的探索 ...

  5. 微信小程序性能优化之一

    微信小程序性能优化之一 原文:微信小程序性能优化之一 性能优化 界面和业务逻辑之间事件交互 小程序调用native Native回调小程序 图片源文件优化 渲染优化 ----------------- ...

  6. 微信小程序性能优化方案

    文章目录 微信小程序性能优化方案 提高加载性能 小程序代码包准备(下载代码包) 开发者代码注入 页面渲染优化 提升渲染性能 setData工作原理 优化方法 微信小程序性能优化方案 微信小程序如果想要 ...

  7. 滴滴java开发面试题_滴滴出行(小桔科技)亲身面试经验分享,java开发岗

    2020.11.25 概要 本次面试是最近刚面的. PS:本人java开发2年经验,这次面的是滴滴出行(小桔科技)java开发岗. 2020.11.30 滴滴又打来电话了, 预定12.3.星期四面试, ...

  8. 分享哈啰出行小程序架构演进之路

    今天跟大家分享一下哈啰出行支付宝小程序的架构演进之路. 内容主要分四个部分.一是对支付宝小程序的简单介绍和我们的项目背景,二是我们遇到的问题和解决问题的思考,三是我们为了解决这些问题引出的哈啰小程序新 ...

  9. 【微信小程序推广营销】教你微信小程序SEO优化,让你的小程序快人一步抢占先机...

    今年一月份上线的小程序,经过近一年的沉淀发酵,现在也进入了快速发展期. 在未来肯定会有越来越多的小程序诞生,小程序多了就需要搜索,那么如何让自己的小程序在众多的小程序中脱颖而出,这就需要小程序SEO优 ...

最新文章

  1. php 下载网络文件,PHP实现文件下载
  2. struts2的注入参数,获取值
  3. CIO常犯的五个错误
  4. 群组密钥交换的新方法研究与分析【会议】
  5. Log4j配置学习文档之一 log4j配置
  6. Microsoft Jet 数据库引擎打不开文件,它已经被别的用户以独占方式打开,或没有查看数据的权限。...
  7. CvArr、Mat、CvMat、IplImage、BYTE转换
  8. 可浮动的在线qq咨询客服代码
  9. 计算机系女生节条幅,2018女生节横幅 最新女生节横幅标语 2018高校女生节横幅...
  10. ant安装配置使用介绍及eclipse中使用
  11. ElasticSearch分布式架构原理
  12. 【微信小程序】农历公历互相转换
  13. 什么是代码,源文件、编辑和编译?
  14. 正则表达必须包含数字字母和特殊字符
  15. Python 中点法求积分
  16. 获取中国 省市区 js
  17. 给定一个字符类型的数组chas[]
  18. 笔记:文澜:桥接视觉和语言的大规模多模态预训练 WenLan: Bridging Vision and Language by Large-Scale Multi-Modal Pre-Training
  19. 新手小白学影视剪辑50天日入500,她的方法秘籍全在这里了!【覃小龙课堂】
  20. 大数据多维分析常用操作图解 OLAP Operations

热门文章

  1. 从零搭建SSM框架及所遇到问题
  2. 财务分析之资产负债表
  3. Android 打电话实现两种方法
  4. c语言安卓录屏,金舟录屏大师app下载
  5. 大数据时代,我们需要“被遗忘权”(转)
  6. 腾讯发布智能硬件全民WiFi 可提高游戏速度
  7. java微信公众号支付开发平台_微信公众号支付demo,微信公众号支付Java DEMO
  8. 恢复SVN的Replacing操作
  9. 基础图像处理 python+opencv
  10. 用ccs创建一个工程文件