跨端框架深度评测:微信原生、wepy、mpvue、uni-app、taro、chameleon

作者: iOS 发布时间: 2019-08-09 浏览: 864 次 编辑

之前 Taro 团队发布了一篇《小程序多端框架全面测评》,让开发者对业界主流的跨端框架,有了初步认识。感谢 Taro 团队的付出。

不过横评这件事,要想得到更精确的结论,其实非常花费时间。它需要:

  • 真实的动手写多个平台的测试demo,比较各个平台的功能、性能,它们的实际情况到底是不是如文档宣传的那样?

  • 真实的学习每个框架,了解它们的学习曲线,在实际开发中遇到问题时,感受它们的文档、教程、社区生态和技服能力到底怎么样?

我们 uni-app 团队投入两周完成了这个深度评测,并定期更新数据。下面我们就分享下,实际开发不同框架的测试例时遇到的问题,以及在各端的兼容测试结果。在本文里,我们团队基于真实测试数据及各框架官网可采集到的公开数据,希望客观公正地评价各个框架的选型和优劣。但宥于利益相关,本文的观点很可能是带有偏向性的,大家可以带着批判的眼光去看待。

评测实验介绍

  • 开发内容:开发一个仿微博小程序首页的复杂长列表,支持下拉刷新、上拉翻页、点赞。

  • 界面如下:

  • 开发版本:一共开发了6个版本,包括微信原生版、wepy版、mpvue版、taro版、uni-app版、chameleon版(以这些产品发布时间排序,下同),按照官网指引通过cli方式默认安装。

  • 测试代码开源(Github仓库地址:https://github.com/dcloudio/test-framework),
    Tips:若有同学觉得测试代码写法欠妥,欢迎提交 PR 或 Issus

  • 测试机型:红米 Redmi 6 Pro、MIUI 10.2.2.0 稳定版(最新版)、微信版本 7.0.3(最新版)

  • 测试环境:每个框架开始测试前,杀掉各App进程、清空内存,保证测试机环境基本一致;每次从本地读取静态数据,屏蔽网络差异。

  • 测试维度:

    1. 跨端支持度如何?

    2. 性能如何?

    3. 学习门槛

    4. 工具与周边生态

1. 跨端支持度如何

开发一次,到处运行,是每个程序员的梦想。但现实往往变成开发一次,到处调错。

各个待评测框架,是否真得如宣传的那样,一次开发、多端发布?

我们将上述仿微博App依次发布到各平台,验证每个框架在各端的兼容性,结果如下:

测试结果说明:

  • ⭕ 表示支持且功能正常,❌ 表示不支持,其它则表示支持但存在部分bug或兼容问题

  • wepy 宣称计划在未来的2.0版支持其他家小程序,本测试基于wepy官网指引安装的wepy-cli版本为1.7.3,尚不支持多端

  • taro最新版支持了H5端的下拉刷新,但没有动画(本内容更新日期2019年5月20日)

  • chameleon官网未找到stopPullDownRefresh定义,停止页面下拉刷新需分平台编写

通过这个简单的例子可以看出,跨端支持度测评结论:uni-app > taro > chameleon > mpvue >wepy原生微信小程序

但是仅有上面的测试还不全面,实际业务要比这个测试例复杂很多。但我们没法开发很多复杂业务做评测,所以还需要再对照各家文档补充一些信息。
由于每个框架的文档中都描述了各种组件和API的跨端支持程度。我们过了几家的文档,发现各家基本是以微信小程序为基线,然后把各种组件和API在其他端实现了一遍:

  • taro:H5端实现了大部分微信的API,App端和微信的差异比较大。

  • uni-app:组件、API、配置,大部分在各个端均已实现,个别API有说明在某些端不支持。可以看出uni-app是完整在H5端实现了一套微信模拟器,在App端实现了一套微信小程序引擎,才达到比较完善的平台兼容性。

  • chameleon:非常常用的一些组件和API在各端已经实现,这部分的平台差异较少。但大量组件和API需要开发者自己分平台写代码。

  • 跨端框架,一方面要考虑框架提供的通用api跨端支持,同时还要考虑不同端的特色差异如何兼容。毕竟每个端都会有自己的特色,不可能完全一致。

  • taro:提供了js环境变量判断和统一接口的多端文件,可以在组件、js、文件方面扩展多端,不支持其他环节的分平台处理。

  • uni-app:提供了条件编译模型,所有代码包括组件、js、css、配置json、文件、目录,均支持条件编译,可不受限的编写各端差异代码。

  • chameleon:提供了多态方案,可以在组件、js、文件方面扩展多端,不支持其他方式的分平台处理。

  • 跨端框架,还涉及一个ui框架的跨端问题,评测结果如下:

  • taro:官方提供了taro ui,只支持微信小程序和H5两端,不支持App,详见

  • uni-app:官方提供了uni ui,可全端运行;uni-app还有一个插件市场,里面有很多三方ui组件,详见

  • chameleon:官方提供了cml-ui扩展组件库,可全端运行,但组件数量略少,详见

  • 最后补充跨端案例:

  • mpvue:微信端案例丰富,未见其它端案例

  • taro:微信端案例丰富,百度、支付宝、H5端亦有少量案例

  • uni-app:微信、App、H5多端案例丰富,官方示例已发布到7端

  • chameleon:有一个滴滴内部案例:青桔单车。还未见到外部案例。

综合以上信息,本项的最终评测结论:uni-app > taro > chameleon > mpvue > wepy原生微信小程序

2. 跨端框架性能如何

跨端框架基本都是compiler + runtime模式,引入的runtime是否会降低运行性能?

尤其是与原生微信小程序开发相比性能怎么样,这是大家普遍关心的问题。

我们依然以上述仿微博小程序为例,测试2个容易出性能问题的点:长列表加载、大量点赞组件的响应。

2.1 长列表加载

仿微博的列表是一个包含很多组件的列表,这种复杂列表对性能的压力更大,很适合做性能测试。

从触发上拉加载到数据更新、页面渲染完成,需要准确计时。人眼视觉计时肯定不行,我们采用程序埋点的方式,制定了如下计时时机:

  • 计时开始时机:交互事件触发,框架赋值之前,如:上拉加载(onReachBottom)函数开头

  • 计时结束时机:页面渲染完毕(微信setData回调函数开头)

Tips:setData回调函数开头可认为是页面渲染完成的时间,是因为微信setData定义如下(微信规范):

字段类型必填描述
dataObject这次要改变的数据
callbackFunctionsetData引起的界面更新渲染完毕后的回调函数

测试方式:从页面空列表开始,通过程序自动触发上拉加载,每次新增20条列表,记录单次耗时;固定间隔连续触发 N 次上拉加载,使得页面达到 20*N 条列表,计算这 N 次触发上拉到渲染完成的平均耗时。

测试结果如下:

说明:以400条微博列表为例,从页面空列表开始,每隔1秒触发一次上拉加载(新增20条微博),记录单次耗时,触发20次后停止(页面达到400条微博),计算这20次的平均耗时,结果微信原生在这20次 触发上拉 -> 渲染完成 的平均耗时为876毫秒,最快的uni-app是741毫秒,最慢的mpvue是4493毫秒

大家初看这个数据,可能比较疑惑,别急,下方有详细说明

说明1:为何 mpvue/wepy 测试数据不完整?

mpvuewepy 诞生之初,微信小程序尚不支持自定义组件,无法进行组件化开发;mpvuewepy 为解决这个问题,将用户编写的Vue组件,编译为WXML中的模板(template),变相实现了组件化开发能力,提高代码复用性,这在当时的技术条件下是很棒的技术方案。

但如此方案,在页面复杂、组件较多的时,会大量增加页面 dom 节点数量,甚至超出微信的 dom 节点数限制。我们在 红米手机(Redmi 6 Pro)上实测,页面组件超过500个时,mpvuewepy 实现的仿微博App就会报出如下异常,并停止渲染,故这两个测试框架在组件较多时,测试数据不完整。这也就意味着,当页面组件太多时,无法使用这2个框架。

dom limit exceeded please check if there's any mistake you've made

Tips:wepy在400条列表以内,为何性能高于微信原生框架,这个跟自定义组件管理开销及业务场景有关(wepy编译为模板,不涉及组件创建及管理开销),后续对微博点赞,涉及组件数据传递时,微信原生框架的性能优势就提现出来了,详见下方测试数据。

说明2:为什么测试数据显示uni-app 会比微信原生框架的性能略好呢?

其实,在页面上有200条记录(200个组件)时,taro 性能数据也比微信原生框架更好。

微信原生框架耗时主要在setData调用上,开发者若不单独优化,则每次都会传递大量数据;而 uni-apptaro 都在调用setData之前自动做diff计算,每次仅传递变动的数据。

例如当前页面有20条数据,触发上拉加载时,会新加载20条数据,此时原生框架通过如下代码测试时,setData会传输40条数据

复制代码data: {  
    listData: []  
},  
onReachBottom() { //上拉加载  
    let listData = this.data.listData;  
    listData.push(...Api.getNews());//新增数据  
    this.setData({  
        listData  
}) //全量数据,发送数据到视图层  }

开发者使用微信原生框架,完全可以自己优化,精简传递数据,比如修改如下:

复制代码data: {  
    listData: []  
},  
onReachBottom() { //上拉加载  
    // 通过长度获取下一次渲染的索引  
    let index = this.data.listData.length;  
    let newData = {}; //新变更数据  
    Api.getNews().forEach((item) => {  
        newData['listData[' + (index++) + ']'] = item //赋值,索引递增  
    })   
this.setData(newData) //增量数据,发送数据到视图层  }

经过如上优化修改后,再次测试,微信原生框架性能数据如下:

从测试结果可看出,经过开发者手动优化,微信原生框架可达到更好的性能,但 uni-apptaro 相比微信原生,性能差距并不大。

这个结果,和web开发类似,web开发也有原生js开发、vue、react框架等情况。如果不做特殊优化,原生js写的网页,性能经常还不如vue、react框架的性能。

也恰恰是因为Vuereact框架的优秀,性能好,开发体验好,所以原生js开发已经逐渐减少使用了。

复杂长列表加载下一页评测结论:微信原生开发手工优化,uni-app>微信原生开发未手工优化,taro > chameleon > wepy > mpvue

注:有人以为uni-app和mpvue是一样的,早期uni-app确实使用过mpvue,但后来因为性能和vue语法支持度问题已经重新开发了。

2.2 点赞组件响应速度

长列表中的某个组件,比如点赞组件,点击时是否能及时的修改未赞和已赞状态?是这项测试的评测点。

测试方式:

  • 选中某微博,点击“点赞”按钮,实现点赞状态状态切换(已赞高亮、未赞灰色),

  • 点赞按钮 onclick函数开头开始计时,setData回调函数开头结束计时;

在红米手机(Redmi 6 Pro)上进行多次测试,求其平均值,结果如下:

说明:也就是在列表数量为400时,微信原生开发的应用,点赞按钮从点击到状态变化需要111毫秒。

测试结果数据说明:

  • wepy/mpvue 测试数据不完整的原因同上,在组件较多时,页面已经不再渲染了

  • 基于微信自定义组件实现组件开发的框架(uni-app/taro/chameleon),组件数据通讯性能接近于微信原生框架,远高于基于template实现组件开发的框架(wepy/mpvue)性能

组件数据更新性能测评:微信原生开发,uni-app,taro > chameleon > wepy > mpvue

综上,本性能测试做了2个测试,长列表加载和组件状态更新,综合2个实验,结论如下:

微信原生开发手工优化,uni-app>微信原生开发未手工优化,<code style="box-sizing: border-box; font-family: SFMono-Regular, Consolas, "Liberation Mono", Menlo, Courier, monospace; font-size: 12px; padding: 0