历经近 20 个月打磨,滴滴跨端方案 Chameleon 终于开源了 , 真正专注于一套代码运行多端。
背景
微信 10 亿月活(超过网民数量,用户多个账号)、支付宝 4 亿月活、百度 3.3 亿月活;2018 Q3 中国 Android 手机占智能手机市场超过 80%;无论 BAT 还是 Android 快应用都是中国互联网用户的真正用户入口,作为小型互联网公司都希望能搭上小程序的风口,从而蹭一波流量。
计算机技术历史发展告诉我们,每一种新技术出现都会经历”各自为政”的阶段,小程序技术也不例外。微信小程序作为首创者,虽然其他小程序都在技术实现原理、接口设计上进行刻意模仿,但是作为一线开发者面对同样的应用实现往往需要重复开发、测试,从前 1 单位的工作量变成了 N 单位的工作量。
滴滴的研发工程师是其中最显著的”受害者”之一,滴滴出行在微信钱包、支付宝、Android 快应用都有相关入口,用户流量占比不低。
各类小程序已经能覆盖中国所有网民,从 Facebook 在 2013 年开源 react,这个项目本身越滚越大。从最早的 WebUI 引擎衍生的 ReactNative 项目,目标更是宏伟。
Vue.js 于 2014 年左右发布,逆流而上占据了大量用户群体,2016 年阿里巴巴也基于 Vue 发布了 Weex 项目,可以用 Vue 编写 NativeAPP。
Google 在 2018 年末正式发布了面向未来的跨 Andoid、IOS 端 Flutter1.0.0,作为面向未来的跨端框架,前景一片光明。
解决方案
虽然不同的端框架环境千变万化,无论各类小程序还是 Weex、React-Native、Flutter、快应用,它们万变不离其宗的是 MVVM 架构设计思想。
Chameleon 希望既能用一套代码完成所有端需求,将相同的业务逻辑完成收敛到同一层系统里面,又不会因为项目的抽象一致导致可维护性变差。
让 MVVM 跨端环境大统一:以各个跨端技术 ( Weex、React-Native、WebView/浏览器、Flutter ) 和产品业务 ( 微信小程序、快应用、支付宝小程序、百度智能小程序、今日头条小程序、其他各类小程序 ) 的共同技术特点——MVVM 架构设计, 以统一 MVVM 跨端架构平台为目标的程序语言框架 Chameleon ( 任意使用 MVVM 架构设计的终端,都能以 Chameleon 开发并运行 ) 。
View
ChameleonSDK 包括各类小程序、Web 端、客户端 ( React-Native、Weex、Flutter ),目前支持微信小程序、Web、Weex 三类,后续支持更多 MVVM 为标准的端。
View Model
CML ( Chameleon MarkupLanguage ) 是框架设计的一套标签语言,结合基础组件、事件系统、数据绑定,可以构建出页面的结构。同时为了降低学习成本支持类 VueTemplate。
原理
久经考验
2017 年微信小程序发布时,滴滴作为白名单用户首先开始尝试接入。这时候我们专门成立了一个 1-2 人的小项目组,完成一个名为 MPV 的项目,一期目标是“不影响用户发挥,不依赖框架方的原则性实现一套代码运行 Web 和微信小程序”。
MPV 研发完成后,在多个项目实践中,确实完成了超过 90% 代码重用,总体上开发效率和测试效率都有了明显提升,同时暴露出更多问题,在 MPV 的实践积累下,有了一定的底气和把握,后续的规划更加明确。
- 可维护性问题,没有隔离公用代码和各端差异代码。
- 方向选择错误,MPV 使用了小程序语法标准 ( 小程序的生命周期、API 接口等 ),导致用户使用上无法清晰理解使用规范。
- 各端周边小型差异点太多。
- 模板 DSL 语法不规范。
- 两端界面效果不一致。
- 多端调试成本高。
- 工程化建设落后。
- 不能直接使用各端已有生态组件,即缺乏标准规范接入某个端已有开源组件。
2018 年 4 月我们把跨端项目规模进一步扩大,跨 N 端的解决方案命名为 Chameleon/kmiln/,简写 CML,中文名卡梅龙,意思是使变色龙,意味着要像变色龙一样能适应不同环境的跨端整体解决方案。
Chameleon 在 MPV 的实践积累下,不仅解决了遇到的各种可维护性问题,后续的规划更加明确,目标真正专注于让一套代码运行多端,提供标准的 MVV M 模式统一各类终端。
经过一年内数十位前端开发人员在上百页面中的实践经验积累,在本周正式开源:https://github.com/didi/chameleon。
生产应用举例
易用性好
一套代码运行多端理念,被人挑战最多的如何保证易用性。
- 一致性,多端实现效果一致。
- 简洁性,各端开发定制化空间大,且公用代码不会混杂某端代码。
- 性能好,不能增加产出文件包大小。
- 开发快,整体开发流程要高效。
多态协议
多端合并后各端差异化实现在所难免,一开始是差异化代码和业务逻辑混杂在一起。这就尴尬了,如果你觉得以上不复杂,假设有 4、5 个端呢,业务逻辑掺杂跨端逻辑,产品逻辑别打断,可读性差,需求变更,牵一发动全身,每个端都要测试,跨端代码效率变得适得其反。
下图为各端差异化代码也和物逻辑混合在一起:
多态协议设计的灵感来自于 Apache Thrift – 可伸缩的跨语言服务开发框架,本质上跨端也属于跨语言。 它能让 Chameleon 开发者快速接入各个客户端底层功能或者差异化业务实现,避免可读性差、可维护性差的问题。
多态协议通过定义标准接口 ( interface ),各端模块各自独立实现,编译时和运行时对实现的接口输入输出做检查。
主要2个目标:
- 保障多端可维护性
- 编译时拆分多端代码
当用户按照标准规范扩展个别产品效果多端不一致或特定底层能力多端不一致的的功能时,多态协议可以有效隔离公用代码和各端差异代码,保证”河水不犯井水“。
举例:当你像开发一个图表功能组件时,可能用到 echarts :
- 在项目中分别按照 Web 版本 npm install echarts 和微信版本下载相关文件。
- 然后定义一个多态组件 charts。
- 在 charts/charts.interface 定义该组件的输入和输出。
- 分别在 charts/charts.wx.cml 和 charts/charts.web.cml 里面调用微信版本 ( 可使用微信小程序组件文件夹)和 Web 版本 ( 可调用 .vue 后缀文件 )。
- 最后就能在项目中使用该组件。
产出包里面只包含该组件其中一端的代码,因输入输出的限制,该组件调用上完全一致,不用根据某端做特殊逻辑处理。
你可以将该 echart 多态组件单独放置在一个仓库里面单独维护并发布,其他人无需关系内部细节,直接 npm install echart
即可使用。
学习成本低
VM 层的 CML 语法是关联视图层和逻辑层的抽象 DSL,其有学习成本问题是被热心很多帮助我们的同学提的最多建议,本身其 CML 学习成本已经非常低,无非是数据双向绑定、事件绑定、组件树、条件语句、循环遍历等等。一开始我们是拒绝的,后来综合考虑之下,还是妥协支持了类 Vue 语法,让开发者更快上手 CML。
渐进式接入
很多人已经开发小程序了,又不愿意大多阔斧重新改造,也希望使用 CML 。当然可以,有 2 种方式使用 CML:
业内对比
业内其他框架和我们的目标不一样,我们是希望真正一套代码运行多端,而其他框架无非是“某个小程序语法增强”或者“推广某个框架写小程序 ”,但却是有重合点,列举一下功能对比:
后期规划
理想主义
- 我们忍受不了自己的时间浪费在重复劳动上。
- 要么不做要做就到极致,一套代码运行多端本来就是理想主义,这条路很艰苦,我们却偏执的坚信一定要尽最大努力做出来,作为一个不那么自 信的人,不做到好用是不敢发布出来的。
- CML 框架各个细节都要做到极致,我们不能容忍有设计上的缺陷,所以常常 CML 周会上团队成员讨论 6 个小时直到深夜。
快速开始:https://cmljs.org/doc/quickstart/quickstart.html
常见问题:https://cmljs.org/doc/framework/faq.html
本文出自 滴滴技术微信号(id:didi_tech)