滴滴出行基于 Mpx 的复杂小程序解决方案
如果无法正常显示,请先停止浏览器的去广告插件。
1. 滴滴出行基于Mpx的复杂
小程序解决方案
董宏平
滴滴出行 高级专家工程师
2.
3. 个人介绍
• 2015 年加入滴滴出行
• ⻓期负责滴滴出行 WebApp/小程序业务
• 开源小程序框架 Mpx 核心作者
• 主导确立了滴滴集团内部小程序技术规范,推动
建设了完善的小程序开发生态
• 在前端MVVM开发框架和前端工程化方向有着深
入的研究和丰富的实战经验
• https://github.com/hiyuki
4. • 滴滴出行小程序复杂性介绍
• Mpx小程序框架概览
• 数据响应与性能优化
• 编译构建与包体积优化
• 小程序跨端
• 小程序多语言
• 展望与未来
5. 滴滴出行小程序复杂性介绍
• 复杂的业务逻辑 (多场景/多状态/重地图)
• 庞大的业务体量 (18+业务线/营销业务闭环/总包
体积20M)
• 跨团队合作开发 (10+业务团队)
• 跨多端投放 (微信/支付宝/QQ/字节/Web)
• 多语言支持 (支持中英文切换)
6. • 滴滴出行小程序复杂性介绍
• Mpx小程序框架概览
• 数据响应与性能优化
• 编译构建与包体积优化
• 小程序跨端
• 小程序多语言
• 展望与未来
7. Mpx设计理念
小程序优先的增强型跨端开发框架
https://github.com/didi/mpx
不同于业内主流小程序框架追求将Web MVVM框架(React/Vue)运行在小程序环境中
的思路,Mpx以小程序原生的语法和技术能力为基础,借鉴参考了Vue框架中的优良语法
设计,通过编译和运行时手段对其进行增强扩展,让用户能够以接近Vue的体验和方式来
进行小程序开发,并保持与原生小程序一致甚至更优的性能与包体积。
8. 业内小程序框架异同对比 - 性能与效率的权衡
静态编译型
(uniapp/Taro) 动态渲染型 (Kbone/Taro next/Remax) 原生增强型
DSL Vue/React Vue/React 小程序增强/类Vue
技术方案 静态转译
Vue/React->小程序原生 递归动态模板模拟DOM环境
上层完整运行Vue/React 编译+运行时
小程序原生->类Vue增强
优势 性能表现良好
具备Web迁移能力 Web框架使用不受限
具备完整的Web迁移能力 性能表现优秀
小程序原生使用不受限
缺点 Web框架使用受限
小程序原生使用受限 性能表现较差
小程序原生使用受限 Web迁移能力较弱
(Mpx)
9. Mpx全局架构
runtime
@mpxjs/core
observable store render
lifecycle convertor mixin
platform patch
@mpxjs/api-proxy @mpxjs/fetch
@mpxjs/mock @mpxjs/webview-
bridge
builtInMixins
@mpxjs/webpack-plugin
compile
wxss-loader wxml-loader extractor i18n dependency
json-compiler template-compiler style-compiler wxs runtime
mpx-loader plugin-loader native-loader platform web
main plugin (处理编译配置/管理编译流程/修改编译产物/分包资源处理/包体积分析/…)
webpack
@mpxjs/cli
10. Mpx支持能力概览
开发体验与效率
质量与性能
跨团队开发
数据响应 setData优化 Npm支持
跨端开发 按需构建 多实例Store
模板指令增强 分包资源处理 Packages规范
CSS预处理 包体积优化 原生渐进迁移
ES6+支持 包体积分析 Typescript支持 单元测试支持 I18n支持 SourceMap支持
11. Mpx使用情况
内部: 支持了滴滴集团内部全量小程序业务的
开发,包括但不限于滴滴出行、花小猪
打⻋、橙心优选、⻘桔单⻋等业内Top小
程序应用。
外部: Star 2.8k
Fork 269
Release 274
Commit 3.5k
外部用户数 3k
凭借良好的开发体验和强大的稳定性与
性能,Mpx收获了大量开发者用户的一
致好评。
12. • 滴滴出行小程序复杂性介绍
• Mpx小程序框架概览
• 数据响应与性能优化
• 编译构建与包体积优化
• 小程序跨端
• 小程序多语言
• 展望与未来
13. 数据响应编程
• 符合直觉
• 数据驱动
• 易于描述复杂业务
14. Mpx数据响应实现
attached
initApi
observable data
数据变更
this.setData
基于defineProperty,参考
Vue2核心数据响应实现
initState
initWatch
detached
clearWatchers
initRender
mixin
createComponent
rawOptions
filterOptions
options
Component
15. 数据响应下的setData优化
小程序setData性能优化建议 数据响应接管了setData后,如何调用?
• 避免setData的数据过大 • 全量设置
• 避免setData的调用过于频繁 • 深度diff设置
• 避免将模板中未绑定的数据传入setData • 只设置模板上使用且发生变化的最小数据
16. 基于render函数的setData优化方案
模板编译
• 模板编译生成render函数模拟模板渲染过程,建立
render watcher收集模板数据依赖
• 对模板依赖数据进行局部diff得到最小必要数据
• 异步队列合并一个tick内的数据变更执行setData
渲染函数
• 处理模板中的wxs模块
局部diff
数据变更
run
最小必要数据
异步队列
setData
render watcher
17. Render函数生成流程
template
compile bind-this
(parser) (babel)
raw function
render function
18. Mpx setData优化效果
• 滴滴出行小程序性能评测指标⻓期优秀,在小程序体验分优化专项中,我们全程未对setData进行过任何人
工优化,setData相关检查项就已全部达标;
• 为测试性能优化效果,我们设计了一系列性能评测方案( https://github.com/hiyuki/mp-framework-
benchmark),对业内流行框架进行的全面地测试,结果显示Mpx的整体性能表现为业内最优;
• 下表展示了系列性能测试中的一个子项结果,在该项测试中我们对不同框架编写的测试demo进行了同样的
交互操作,对各个框架中对setData的调用次数及发送的数据体积进行统计:
Mpx Uniapp Mpvue Wepy2 Chameleon Kbone Taro next Native
(未优化)
count 8 14 16 3514 2515 22 9 14
size(KB) 261 274 2127 1124 319 10572 2321 803
19. • 滴滴出行小程序复杂性介绍
• Mpx小程序框架概览
• 数据响应与性能优化
• 编译构建与包体积优化
• 小程序跨端
• 小程序多语言
• 展望与未来
20. Mpx编译构建
• 基于Webpack,兼容大部分Webpack生态
• 基于依赖收集按需构建,输出结果无冗余
• 支持mpx单文件开发
• 支持npm
• 支持CSS预处理、babel、terser
• 支持分包构建与独立分包
• 支持watch模式及模块缓存,支持DLL
• 支持sourceMap生成
• 支持原生小程序生态
• 自带包体积分析工具
21. 小程序资源依赖树
json.workers
app
json.pages
page.json
page.json
pages
json.usingComponents
page.json
page.json
components
json.usingComponents
page.json
page.json
components
json.usingComponents
page.json
page.json
components
json.usingComponents
page.json
page.json
components
json.subpackages
page.json
page.json
subpackages
subpackage.pages
page.json
page.json
pages
json.usingComponents
page.json
page.json
components
page.json
page.json
workers
22. Mpx编译构建流程
init entry(app.mpx)
dynamic add entry
(pages/components)
mpx-loader
render
function
json-compiler
style-compiler
template-compiler
js module
make
seal
extractor
mp assets
23. Npm支持
原生(微信) Mpx
• 需执行npm构建步骤 • 对于所有类型的npm资源都支持按需的依赖分
析构建,构建结果无冗余
• 对于纯js的npm包进行依赖分析构建
• 对于带有自定义组件的npm包,全量copy包内
的miniprogram_dist目录到项目目录下,存在
大量冗余
• 需手动维护配置packNpmRelationList以将特
定的npm资源输出到分包中
• 根据资源依赖关系自动将npm资源输出到正确
的主包或分包,开发者无需额外关注
24. 分包构建
组件与静态资源
根据用户分包配置,串行对
主包和各个分包进行构建,
构建过程对组件与静态资源
进行分包标记,根据小程序
资源访问规则输出到主包或
者分包目录中。
app.json
主包构建/主包资源标记 根目录
分包A构建/分包A资源标记 分包A目录
分包B构建/分包B资源标记 分包B目录
25. 分包构建
JS模块
根据用户分包配置,自动生
成SplitChunksPlugin配置,
将项目中的公共模块输出到
主包或分包bundle中
独立分包
• 独立runtime
• 独立组件与静态资源
• 独立modules
(identifier hack)
26. 小程序包体积分析
Webpack-bundle-analyzer的不足
• 只能统计分析js模块体积,而小程序输出中包含大量非js资源
• 无法以分包维度进行体积统计分析
• 体积来源难以追溯
Mpx包体积分析工具
• 支持全量资源(js与非js)体积统计分析
• 支持以分包维度进行体积统计分析
• 支持通过来源配置分组进行体积统计分析
• 支持按照分组和分包维度配置体积阈值进行体积管控
27. 小程序包体积分组统计
entries
app page.json
page.json
pages page.json
page.json
components
page.json
page.json
modules page.json
page.json
modules page.json
page.json
modules
Self size
当module关联的全部entries
都在某个分组的entries范围
内,该module对应的体积就
属于该分组的self Size
Shared size
当module关联的部分entries
存在于某个分组的entries范
围内,该module对应的体积
就属于该分组的shared Size
traverse & mark
modules
with
entries
info
modules
with
entries
modules with entries info
info
fill size groups
group
self
size
& & shared
size
group
self
size
shared
group self size & shared size
size
28. 小程序包体积分析结果展示
29. 小程序包体积优化总结
• 精简的框架运行时代码,压缩后体积占用<50KB
• 构建过程完整基于依赖分析,只有用户使用到的
资源才会被输出,对于npm资源也是如此
• 强大的分包资源处理能力,分析资源依赖关系自
动确定资源输出位置,有效利用分包体积空间
• 根据用户分包配置抽取公共模块,分包only公共模
块抽取至分包bundle,全局公共模块抽取至主包
bundle,确保全局无模块冗余
• 完整支持Webpack代码优化机制,如tree
shaking,side effects,terser压缩等
• 全维度跨平台条件编译死分支删除,只有目标平
台真实需要的代码才会被输出
• 依赖冗余检测机制,当构建中存在版本不同的冗
余npm依赖时自动报警,提醒用户自查处理
• 强大的包体积分析能力,完全针对小程序技术规
范进行设计,便于进行小程序包体积分析管控
业务案例
• 橙心优选小程序在由原生开发切换为Mpx后,包体积降幅高达43%
• 滴滴出行小程序总包体积已经接近20M,主包仍能保持在1.7M左右
30. • 滴滴出行小程序复杂性介绍
• Mpx小程序框架概览
• 数据响应与性能优化
• 编译构建与包体积优化
• 小程序跨端
• 小程序多语言
• 展望与未来
31. 从多平台支持到小程序跨端
微信.mpx
微信.mpx
支付宝.mpx
微信dist
支付宝dist
支付宝.mpx
百度.mpx
2.0升级
Mpx多平台增强
百度dist
Learn once, write everywhere
Mpx跨平台转换
百度.mpx
Mpx多平台增强
微信dist
支付宝dist
百度dist
Write once, run everywhere
32. Mpx小程序跨端
设计理念
优势特点
• 优先解决小程序跨端问题,支持将Mpx微信小
程序跨端输出至其他小程序平台运行; • • 对于静态部分差异以编译转换为主; 跨端输出产物与目标平台原生代码接近,便于
输出调试;
• • 对于动态部分差异以运行时抹平为主; 条件编译确保只有目标平台的相关代码会被最
终输出,无代码冗余,包体积性能良好;
• 对于框架无法处理的差异,提供强大灵活的条
件编译能力,便于用户自行处理抹平。 • 支持对原生生态进行跨平台输出,例如将
@vant/weapp输出到其他小程序平台中运
行。
已支持平台
•
微信、支付宝、百度、头条、QQ、京东、快
应用(webview)、Web(Vue)
33. 运行时抹平
Mpx运行时增强(数据响应/setData优化/事件代理/refs/i18n/…)
beforeCreate
beforeMount
updated
全局API抹平
(@mpxjs/api-proxy)
Mpx统一生命周期
created
Mixin
mounted
平台驱动层(platform patch)
微信生命周期
支付宝生命周期
destroyed
基础能力抹平
(builtInMixins)
配置转换(convertor)
用户⻚面/组件配置
34. 编译转换
业务代码
Mpx运行时抹平
条件编译
wxRules
源平台代码
aliRules
RulesRunner
目标平台代码
静态代码转换
目标平台代码
swanRules
目标平台增强
目标平台小程序
35. 文件维度条件编译
• 通过文件中后缀标识平台
• 基于enhanced-resolve实现
• 可以与webpack alias结合,为npm中的文件
创建条件编译副本
components/card.wx.mpx
微信
支付宝
components/card.ali.mpx
其他
components/card.mpx
36. 区块维度条件编译
• 使用区块mode属性标识平台
• 优先使用存在mode标识的区块
37. 代码维度条件编译
• 通过平台环境变量进行条件判断
• 所有代码维度条件编译均能移除
条件死分支
38. 属性维度条件编译
• 当平台差异只存在于节点属性维度时,使用代码维度条件编译较为冗余,子树难以维护
• 使用atMode对属性进行条件编译声明,让代码变得清晰简洁
39. 跨端输出Web
• 小程序webview能力有限,营销业务存在同时产出小程序原生和端内H5的诉求
• Web的开放和灵活程度高于小程序,从小程序输出web的可行性更高
• Mpx中增强能力设计借鉴于Vue,使用Vue承载web输出时大多数能力不用重新实现
• 框架内提供基于Vue的小程序基础组件封装,抹平基础组件差异
• 使用条件编译 + 端内bridge抹平底层能力差异
40. Mpx输出Web
基础组件封装 Api封装抹平 ⻚面路由 JSON解析实现
样式隔离 组件间关系 抽象节点 …
小程序基础能力抹平
编译注入
processTemplate
processJSON
init entry(app.mpx)
processStyles
.vue
vue-loader
js module
processScript
make
seal
mpx-loader (web)
web assets
41. 小程序⻚面路由模拟
visibilitychange
page/profile
路由Api调用trace
用户路由
操作
page/home
history.length
路由栈变化
信息
Mpx-keep-alive
activated/
deactivated
Page.onShow
router-view Page.onHide
cache instance/
instance.$destro
y Page.onLoad
page/index
router.beforeEach
⻚面路由栈
Page.onUnload
42. 按需组件封装
• Vue组件本身存在性能开销
• 小程序业务中大部分view/text节点与html基础标签等价
• 模板编译时基于用户使用能力,按需注入封装组件
43. Mpx跨端能力业务应用
微信小程序
支付宝小程序
原生小程序⻚面
端内H5
44. • 滴滴出行小程序复杂性介绍
• Mpx小程序框架概览
• 数据响应与性能优化
• 编译构建与包体积优化
• 小程序跨端
• 小程序多语言
• 展望与未来
45. Mpx多语言支持
• 基于小程序双线程架构设计
• 完整的跨端支持
• 支持computed模式与异步加载
46. Mpx多语言支持
编译
运行时
翻译函数模板
多语言字典
输出小程序
wxs-i18n-loader
wxs翻译函数
wxs -> js
注入模板 模板i18n调用
注入js运行时 js i18n调用
注入vue-i18n web i18n调用
wxs转译为js
js翻译函数
输出web
47. Computed模式与异步加载
Wxs模式(默认)
Computed模式
• 无通信开销,性能最优 • 存在额外通信开销
• 无使用限制 • 循环渲染时存在使用限制
• 包体积占用较大,语言包同时存在于wxs和js当中 • 包体积占用较小,语言包只存在于js当中
• 语言集在编译时全量注入,不支持异步加载 • 支持运行时异步加载语言包
48. • 滴滴出行小程序复杂性介绍
• Mpx小程序框架概览
• 数据响应与性能优化
• 编译构建与包体积优化
• 小程序跨端
• 小程序多语言
• 展望与未来
49. 展望与未来
• Webpack5构建升级,大幅提升构建速度
• Vue3数据响应升级,支持composition api
• 单元测试进一步完善,完整支持jest mock
• E2E自动化测试支持
• Mpx-cube-ui跨端组件库开源
• 支持局部组件运行时渲染
50. 没有最完美的解决方案,只有最适合自己的
51.
52.
53.