原创: 嘉宾-张楠 前端
开源中国 vue
以往咱们说某一功能跨多端,每每是指在诸如 PC、移动等不一样类型的设备之间都能实现;或者更加具体一点,指的是“跨平台”,多是大到跨操做系统,好比 Windows、macOS、Linux、iOS 与 Android 等,多是小到跨某个具体技术的不一样实现库。git
可是今天咱们要介绍的是关于跨 MVVM 架构模式各类环境的场景。github
Chameleon 是一套开源跨端解决方案,它的目标是让 MVVM 跨端环境大一统,实现任意使用 MVVM 架构设计的终端,都能使用其进行开发并运行。 web
在这样一个 MVVM 环境中,涉及到了 Weex、React-Native、WebView/浏览器与 Flutter 等各类跨端技术,还有它们实现的具体业务产品,好比微信小程序、快应用、支付宝小程序、百度智能小程序、今日头条小程序与其它各种小程序。ajax
也许你发现了,这里提到了许多种“小程序”,虽然最先微信小程序的概念甚至早期版本出现的时候,有过很多不看好的声音,可是随着它不断发展,目前已经成为了大众生活不可或缺的应用形态。vuex
马化腾透露过,截至 2018 年 11 月有 150 万微信小程序开发者,小程序应用数量超过 100 万,覆盖 200 多个细分行业,日活用户达到 2 亿。这样的成功经验与几乎触及到生活方方面面的巨大流量入口,你们都想入场,因而能够看到后来其它公司纷纷给出了相似的小程序方案。redux
另外一方面,除了小程序百花齐放,2018 年小米、华为、OPPO 等 10 家安卓手机厂商还结成了快应用联盟,而且前后发布了一系列快应用。小程序
Chameleon 目标就是要跨这些端,而随着各家不一样实现愈来愈多,跨端场景也不断变得更加复杂。咱们采访了 Chameleon 创始人张楠,请他为读者具体分享了 Chameleon 在这个过程当中的成长。后端
项目地址:https://github.com/didi/chame...
本文是 Chameleon 首次对外公开实现原理!
干货超多,包括:
关于这个问题能够从行业背景讲起。
中国互联网络信息中心(CNNIC)发布的《中国互联网络发展情况统计报告》显示,截至 2018 年 6 月,我国网民规模达 8.02 亿人,微信月活 10 亿 、支付宝月活 4 亿、百度月活 3.3 亿;另外一方面,2018 Q3 中国 Android 手机占智能手机总体的比例超过 80%,月活约 6 亿。
BAT 与 Android 成为了中国互联网真正的用户入口。但凡流量高的入口级别 APP 都但愿作平台,成为一个生态平台和互联网流量入口,大量第三方应用的接入,从业务层让公司 APP 关联上更多企业的利益,而且拥有更强的生命力;从技术层面能够利用“本地能力接口层”收集大量用户数据,从消费互联网到产业互联网须要大量各行各业基础用户数据线索进行驱动和决策。
在这么一种背景下,再结合计算机技术的发展历史,咱们知道每一种新技术的出现都会经历“各自为政”的阶段,小程序技术也不例外,因此咱们看到了其它各类小程序平台出现。
微信小程序做为独创者,虽然其它小程序都有在技术实现原理、接口设计上刻意模仿,可是做为一线开发者在不一样平台发布小程序,每每仍是须要重复开发、测试,从前 1 单位的工做量变成了 N 单位的工做量。而这还没算上快应用等其它入口。
这种状况下,滴滴的研发工程师是其中最显著的“受害者”之一,滴滴出行在微信钱包、支付宝、Android 快应用都有相关入口,并且用户流量占比不低。
研发同窗在端内既追求 H5 的灵活性,也要追求性能趋近于原生。面对入口扩张,主端、独立端、微信小程序、支付宝小程序、百度小程序、安卓厂商联盟快应用,单一功能在各平台都要重复实现,开发和维护成本成倍增长。
迫切须要一个只维护一套代码就能够构建多入口的解决方案,因而咱们着手去打造了 Chameleon(CML,卡梅龙)这么一个项目,真正专一于让一套代码运行多端。
MVVM 也就是 Model View ViewModel,它本质上是 MVC( Model View Controller)的进化版本,将 View 的状态和行为抽象化,使得视图 UI 和业务逻辑分开。
它是一种让数据驱动反射视图的模式,发展到如今可能会偏离它的初衷了,更像是一个视图数据间的“通讯协议”,让终端开发变得更加单纯,这是一种趋势,面向将来框架都采用这种模式。
Facebook 在 2013 年开源 React,React 这个项目自己是一个 Web UI 引擎,随着不断发展,它衍生出 React Native 项目,用来编写原生移动应用。正是它给跨端方向带来了 MVVM 模式。
Vue.js 于 2014 年左右发布,逆流而上占据了大量用户群体,2016 阿里巴巴也基于它发布了 Weex 项目,使得能够用 Vue 编写 Native App。
Google 在 2018 年底正式发布了面向将来的跨 Android、iOS 端的 Flutter 1.0.0。
咱们知道终端开发离不开三大要素——界面表现(结构、外观)层、逻辑处理层与系统接口层(网络、存储与媒体等)。
开发者编写代码时在初始化阶段(生命周期)调用“界面表现层”界面模型的接口绘制界面,当用户触摸界面时,“界面表现层”将事件发送给用户“逻辑处理层”,后者通过条件判断再处理并反馈到用户界面,处理过程可能须要调用“系统接口层”,反馈过程须要调用“界面表现层”的接口。
常规的终端开发架构模式下,不管是 Web 端、Android 端仍是 iOS 端的项目开发,都强依赖各端的环境接口,特别是依赖界面相关模型设计。
iOS 系统下绘制界面基于 Objective-C 语言环境下的 UIKit 框架;Android 系统下用户绘制界面基于 Java 语言环境,由 LayoutInflater 处理 XML 结构层次树;Web 端使用 DOM 模型和 CSS 来描述绘制界面。
MVVM 中的关键是它经过 ViewModel 这一层将界面和逻辑层完全隔离开来,负责关联界面表现和逻辑处理层的响应事件(update/notify)关系,这一“隔离层”上下通讯足够规范、足够纯净单一。
Model 进行逻辑处理是纯业务响应逻辑,任何一种语言均可以实现,你能够用 Android 的 Java,也能够用 iOS 的 Objective-C,你心情好用“世界第一语言 PHP”也能实现。
之因此广泛选择 JavaScript,很大程度是由于在这个领域内它的优势显著,如学习成本低、天生具有跨端属性、虚拟机(V八、JavaScriptCore)和各方向组件建设较好、生态活跃。
而系统接口层则更简单了,只需穷举统一基础接口+可扩展接口能力便可。
具体来看看各类 MVVM 方案都是怎么样的。
React Native、Weex 与快应用的 MVVM
开发者编写的代码在虚拟机(V八、JavaScriptCore)里面运行,虚拟机容器里面包含扩展的系统基础接口。运行时,将描述界面的数据(主要是 CSS+DSL 所描述内容)经过通讯层传递给 Android、iOS 端的渲染引擎,用户触摸界面时,经过通讯层传递给虚拟机里面的业务处理代码,业务处理代码可能调用网络、储存与媒体等接口,最后再次反馈到界面。
Flutter 的 MVVM
Flutter 和 RN 的最大区别在于将“JavascriptCore/V8+JS”替换成“C++ 实现的 engine+Dart 实现的 Framework+静态类型 Dart+编译成机器码”。
Flutter 的方案以下图所示:
Service 其实就是本地能力接口层,Widget 树是视图层模型。
Flutter 和 RN 的使用面设计上相似,Flutter 文档中提到“In Flutter, almost everything is a widget.”,widget 的调用从 RN 的 JSX 变成 Flutter 的 widget 调用,UI 的外观描述从 RN 的 CSS(文本样式、布局模型、盒模型)到定制化 Flutter Widget(textStyle 、Layout Widget、Widget)。
本质上 Flutter 也是 MVVM 架构,逻辑层经过 setState 通知视图层更新,必定程度上这也是为何 Flutter 敢说能转成 Web 框架的缘由,核心仍是基于这类数据驱动视图架构模式,业务代码不会深度依赖任何一端特有的“视图模型”。
各种小程序的 MVVM
小程序本质上和 Weex、React Native 的设计思路基本同样,最大区别在于前者仍是用浏览器 WebView 作渲染引擎,然后者是单独实现了渲染引擎(因此大量的 CSS 布局模型不支持)。
首先任何一份应用层的高级语言代码块分红几层:语言层(Language)、框架层(Framewrok)与库层(Library):
对应到 Chameleon 就是这样:
具体到实现原理全景架构图以下:
你能够理解 Chameleon 为了实现“让 MVVM 跨端环境大统一”的目标作了如下工做:
实现思路很简单,全部设计为了 MVVM 标准化,不作多余设计,因此宏观的角度就像 Node.js(libuv)同时运行在 Windows 和 macOS 系统,都提供了一个跨平台抽象层。
从 MVVM 角度来看的话:
一句话:基于 Chameleon 开发,效率会愈来愈高。
各个端的涌现,让本来是 1 的工做量由于多端存在而变成 N 倍,使用 Chameleon,工做量会变回 1.2。这多出来的 0.2 工做量是要处理各端的差别化功能,好比如下场景:
这种各端差别较大的例子,随着业务的积累,能够变成了一个个业务组件单独维护,后面也不须要重复开发了,且反推产品体验一致化,组件三层结构“CML框架内置组件->CML扩展组件->业务开发者本身扩展的多态组件”达成 100% 统一。
随着组件积累业务开发工做量越来少,工程师能够专一作更加有意义的事情,这就是 Chameleon 存在的目的。
基于统一的跨端抽象,用户在 Chameleon 项目持续维护过程当中,Chameleon 发布新增一个端以后,你的业务代码基本不用改动便可无缝发布成新端。
好比这个 cml-yanxuan 项目开发时支持 3 个端,后面新增了百度、支付宝小程序端,原有代码直接能跑起来运行 5 个端,一端所见即多端所见。
开发时只能跑 3 个端
原有代码无缝支持 5 个端
另外特别强调的是,对于大公司团队,若是有很强的技术能力,但愿开发的代码掌控在本身手里,对输出结果有更好控制能力。其实 Chameleon 内置组件和内置 API 是能够替换的,那么全部组件都是业务方本身开发了,哪天不想用了直接导出原生组件便可离开 Chameleon,以下图:
咱们以为 Chameleon 与其它解决方案的最大区别在于其它框架都是小程序加强,即用 Vue 或者 React 写小程序,这些框架官方给的已接入例子也都是跑微信小程序。
它们更加相似 Chameleon 的前身 MPV(Mini Program View),即考虑如何加强小程序开发。2017 年微信小程序发布时,滴滴做为白名单用户首先开始尝试接入,开始面对重复开发的难题。
这时候咱们专门成立了一个小项目组,完成一个名为 MPV 的项目,一期目标是“不影响用户发挥,不依赖框架方的原则性实现一套代码运行 Web 和微信小程序”。
看着很美好,用这样的方案实现 Web 端和小程序端,也确实完成了超过 90% 代码重用,整体上开发效率和测试效率都有了必定提高,可是却不是真正意义上的跨多端统一。
单独说到 Chameleon 与 Taro 的区别,整体上看,能够归为这样一个表:
表中每一项都是在作跨端方案时须要考虑到的。咱们说除了 Chameleon,其它方案都只是在对小程序进行加强,或者说是模仿微信小程序的 API 和组件的接口设计。
Taro 是经过将 JSX 转成小程序模板,在其它端模拟微信小程序的接口和组件,让其它端更像微信小程序,业务开发时不一致的地方须要环境变量判断差别分别调用,会形成端差别逻辑和产品逻辑混合在一块儿。
此外,它要跟随小程序更新,业务方会有双重依赖;其它端的和小程序不能保持一致,用户要各类差别化兼容,不利于维护。
那 Chameleon 呢?Chameleon 把这些问题都考虑到了,因此在早期伪跨端 MiniProgram View 成型以后不断演进的过程当中,把它发展成为一个真正的跨多端方案。
前边的表格显示了,Chameleon 既考虑统一性,又考虑差别性,且差别性不会影响可维护性;当各端差别确实太大,那就不要用一套代码实现多个端同一页面,而是统一公用组件。
这还只是拿 Chameleon 与 Taro 的重合点进行了对比,可是别忘了 Chameleon 不只仅是前端框架,它:
另外,将来还将带来如下能力:
当前的各种小程序和 Native 跨端框架,相似当年多个浏览器时,Safari、Chrome、Firefox、IE 6/7/8/九、Android 浏览器等盛行的时代。以这个来类比,那么 Chameleon 的接口组件设计上更像一个 jQuery。
网络请求有的是 XHRHttprequest 有的是 ActiveXObject,jQuery 考虑的是用户须要什么,须要一个网路请求接口,支持 get、post 等,因此 jQuery 写一个既非 ActiveXObject 又非 XHRHttprequest 的名为 $.ajax 接口,提供一个封装网络接口,你不用关心内部在不一样端怎么调用的,jQuery 内部会帮你兼容。
Chameleon 也是同样的思路,全部的接口设计都是真正能兼容跨全部的端,没有差别性,并且只保留当前所在端的接口调用代码:IE 里面只保留 ActiveXObject,Chrome 只保留 XHRHttprequest。
Chameleon 的接口设计上比 jQuery 更强的地方在于,使用标准的多态协议,保障可维护性,性能上只保留当前端代码,且将多态协议暴露出来,让用户也能扩展本身想要的 API(类比 $.xxx)。
固然时代已经变了,监听视图不在是 $('#xxx').click(fn),而是 MVVM 数据驱动视图方式了,因此提供了 Chameleon 双向绑定这样的 VM 层。
前面讲到,2017 年的时候,咱们完成一个名为 MPV 的项目,一期目标是不影响用户发挥,不依赖框架方的原则性实现一套代码运行 Web 和微信小程序。
当时缺少小程序资料是遇到的最大问题(就更别提今天讲到的业内这么多解决方案了),当时惟一一个能够参考的开源项目是 WEPT,WEPT 是一个微信小程序实时开发环境,它的目标是为小程序开发提供高效、稳定、友好、无限制的运行环境。它的设计思路是在 Web 端模仿小程序环境执行。
因而咱们在开发 MPV 时考虑了两种实现策略:
一、在 Web 端像 WEPT 同样 mock 小程序环境;就像微信开发者工具里面也模拟了小程序执行环境,WAServie、WAWebview 提供的两套环境源码作底层,在页面中开启三个独立运行环境运行并用 iframe 通信模拟微信小程序的 3 个 Webview 之间的联通关系。
二、逐个转译代码支持小程序,缺点是可能会有 edge case 须要处理以及潜在的 bug 会比较多。
最终在看完 WEPT 源码和微信开发者工具的状况下,咱们明确放弃了第 1 条实现策略,选择了逐个转译代码支持小程序的路线,主要缘由是于 Web 端兼容微信全部的功能,尺寸过于庞大。
通过三个月紧锣密鼓的开发终于实现了初版本 MPV:
通过实现几个 demo 以后,开始执行迁移计划:
MPV 在 Webapp 上实践最终实现效果以下:
最终实现效果挺美好,也确实完成了超过 90% 的代码重用,整体上开发效率和测试效率都有了明显提高。
可是在后续实践过程当中,发现存在大量的问题,而且项目越大问题越凸显出来,总结以下:
在 MPV 的实践积累下,有了必定的底气和把握,后续的规划更加明确。2018 年 4 月咱们把跨端项目规模进一步扩大,想要作一个真正跨 N 端的解决方案,目标是提供标准的 MVVM 架构开发模式统一各种终端。这就是 Chameleon 的出现契机。
Chameleon 真正想要一套代码运行多端,总结下来要解决几大问题:
目标理想业务形态是这样的:
图中上半部分是传统开发方式,下半部分 Chameleon 的模式抽象出了 UI 渲染层和本地接口能力层,业务代码一部分简单页面由 XEditor(h5Editor 的前身)编辑工具产出,另外一部分工程师使用 Chameleon 开发,不止解决跨端问题,还弥补改进了工程开发过程当中的效率、质量、性能与稳定性问题,让工程师专一有意义的业务,成长更快。
首个 Native 渲染引擎选择——小程序架构、RN/Weex 架构
从 MPV 到 Chameleon,外界看来最明显的变化是从跨 2 端(Web、小程序)升级到跨多端(Web、小程序、Android、iOS),最开始纠结于首个端上版本的渲染引擎使用小程序架构仍是 RN/Weex 架构。
RN/Weex 网上有大量资料可查,可是小程序方面则否则。千辛万苦搜索以后,根据一位知道内情的朋友的描述分享,才有了必定的了解。
这里分享几个印象深入的要点:
最终多方面分析以下:
虽然小程序方案看起来很简单,但其实不少细节点须要大量打磨,从确认方案到真正能够跑起来能够线上发布,仅仅花费在终端上的研发人力为 20P*6 个月,微信小程序团队的目标和咱们跨端目标不同,他们投入这么多成本是值得的,咱们为了跨端不必投入这么高成本。
因此咱们选择放弃小程序渲染方案,而使用已开源的 RN/Weex 方案。
第一个版本最终使用 Weex,包括团队同窗去看了 Weex 源码实现。
在总体设计上仅仅使用 Weex 渲染功能,外层包装接口,保障后续能有更高扩展性。
Chameleon Native SDK
针对 Native SDK 咱们主要从原生能力扩展、性能与稳定等三个方面作了工做。
如下是性能方向中的首屏加载时间的优化数据,原有 H5 使用 SSR(Server Side Render)已经算是最快的 Web 首屏技术方案了(不考虑优化后端多模块耗时的 BIGPIPE),它保持在 1.5 秒如下,在优化后降到 0.5 秒左右。
性能优化中咱们有一个关于执行速度的 TODO 计划。一样是跨端,Flutter 之因此比 Weex 和 RN 执行速度快,主要缘由是前者是编译型,客户端机器运行前已是 CPU 可识别的机器码;后者是解释型,到客户端运行前是字符串,边编译边执行,虽然作了 JIT 尽可能优化,差距仍是较大。其实在这中间还有一个抹平了不一样 CPU 架构下机器码差别的中间码;固然前提是开发语言改为静态类型,这里不做展开。
本来分 5 次开发的 Web 端、支付宝小程序、快应用、微信小程序、Native 端变成了 1.2 次左右开发了。最重要的是随着业务级别各端差别化的多态组件和跨端组件积累,后续 1.2 工做量也会变成 0.8,0.4 的优化主要来自两个方面:
咱们的最终目标是提供标准的 MVVM 架构开发模式统一各种终端。
接下来的具体 roadmap 以下表所示:
欢迎有共同愿景的同窗加入咱们一块儿共建,往仓库贡献本身的代码。
项目地址:https://github.com/didi/chame...
QQ 群:
公众号:
张楠,Chameleon 创始人,技术团队负责人,前百度资深工程师,终身学习者。