【FCon上海】与行业领袖共话AI大模型、数字化风控等前沿技术。 了解详情
写点什么

滴滴出行小程序体积优化实践

  • 2021-06-05
  • 本文字数:4690 字

    阅读完需:约 15 分钟

滴滴出行小程序体积优化实践

AI 大模型超全落地场景&金融应用实践,8 月 16 - 19 日 FCon x AICon 大会联诀来袭、干货翻倍!

背景


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


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


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


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


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


体积控制


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


▍基础优化手段


对于小程序来说,基础的包体积优化手段包括:资源压缩/去除代码冗余/资源 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+空间留给业务迭代还是比较充裕的。而主包的体积在理想条件下是可以长久保持不变的,就不会因为业务需求的不断开发反复导致主包体积临近超标,不再需要为主包体积感到焦虑。


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


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


总结


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


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


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



头图:Unsplash

作者:滴滴技术

原文:https://mp.weixin.qq.com/s/MGpFsz0jZBuBYx3R1HQurg

原文:滴滴出行小程序体积优化实践

来源:滴滴技术 - 微信公众号 [ID:didi_tech]

转载:著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

2021-06-05 08:004234

评论

发布
暂无评论
发现更多内容

数仓现网案例丨超大结果集接收异常

华为云开发者联盟

数据库 后端 华为云 华为云开发者联盟 企业号 7 月 PK 榜

暑期读书指南 | 用缤纷字体读精品好书,华为阅读上新啦!

最新动态

大型企业数智化转型,工程化体系建设至关重要

用友BIP

数智底座

初探webAssembly | 京东物流技术团队

京东科技开发者

前端 webassembly JavaScrip Blazor WebAssembly 企业号 7 月 PK 榜

Inpaint Anything:一键进行多种图像修补

华为云开发者联盟

人工智能 华为云 华为云开发者联盟 企业号 7 月 PK 榜

值得关注的五个先进代码补全服务

这我可不懂

人工智能 代码补全

HBase Compaction 原理与线上调优实践

vivo互联网技术

HBase 调优参数 Minor Compaction Compaction策略 Major Compaction

AREX:携程新一代自动化回归测试工具的设计与实现

AREX 中文社区

开源 测试工具 回归测试 流量回放

资源成本降低70%!华为MetaERP资产核算的Serverless架构实践

华为云开发者联盟

云计算 后端 华为云 华为云开发者联盟 企业号 7 月 PK 榜

架构训练营模块一作业

Kleven

架构实战营

长连接:ChatGPT流式响应背后的逻辑 | 京东物流技术团队

京东科技开发者

websocket 长连接 企业号 7 月 PK 榜 sse

并发编程-FutureTask解析 | 京东物流技术团队

京东科技开发者

并发编程 源码剖析 FutureTask 企业号 7 月 PK 榜

再获权威认可!MIAOYUN荣获中国信通院一云多芯优秀案例,荣登《云管理产品与服务图谱》

MIAOYUN

中国信通院 一云多芯解决方案 一云多芯 可信云大会 云管理产品与服务图谱

【观察】智能运维的“下半场”,看云智慧如何“开新局”

云智慧AIOps社区

算法 运维 智能运维 大模型 IT运维

MySQL 的解析器以及 MySQL8.0 做出的改进 | StoneDB技术分享 #2

StoneDB

MySQL 数据库 HTAP StoneDB

Java Web应用开发案例|使用AJAX实现省市区三级联动效果

TiAmo

Java Java web 开发实例

一文让你知道等保测评和渗透测试的区别与联系

行云管家

信息安全 渗透测试 等级保护 等保测评

在langchain中使用带简短知识内容的prompt template

程序那些事

人工智能 AI 程序那些事 AI大语言模型 大语言模型

金山云与平凯星辰达成全面战略合作 技术创新模式助力企业数字化转型

PingCAP

金山云 数字化 TiDB pingCAP 平凯星辰

英特尔合作埃森哲推出一套共计34个开源AI参考套件

E科讯

暑假提升休闲两不误,与华为阅读一起开启高质量听书

最新动态

前端程序员入门:先学Vue3还是Vue2?

互联网工科生

vue.js Vue 前端

澜舟科技CEO周明:不过度追求AGI,更看重大模型语言理解能力和应用落地性 | 1号位

澜舟孟子开源社区

印刷行业MES系统解决方案

万界星空科技

开源 MES系统 印刷

从税务管理的数智化转型之路中我们能看到什么?

用友BIP

税务管理

伙伴云「页面」上线!网站、博客、资源库、文档、周报,拖拽即刻实现

联营汇聚

大文件传输过程中的网络拥塞控制方法研究

镭速

大文件传输 网络拥塞问题

用Rust生成Ant-Design Table Columns | 京东云技术团队

京东科技开发者

rust swagger 企业号 7 月 PK 榜 Columns

用友发布业界首个企业服务大模型YonGPT

用友BIP

HTML5智慧景区三维可视化管理平台

2D3D前端可视化开发

智慧景区 智慧旅游 景区三维可视化 数字景区 智慧景区系统

Cloud Kernel SIG 月度动态:支持龙芯和申威架构,合入两个内存新特性

OpenAnolis小助手

开源 架构 内存 内核 龙蜥sig

滴滴出行小程序体积优化实践_语言 & 开发_滴滴技术_InfoQ精选文章