微信小程序如火如荼, 各家小程序快速跟进, 继 App,H5 之后, 小程序平台已跃升为第三大流量平台, 那现阶段快速开发小程序的更优方案是什么? 选择原生开发, 还是借助跨端框架? 每个框架又有何差异?
本文经授权转载, 如下为原文, enjoy!
之前 Taro 团队发布了一篇《小程序多端框架全面测评》, 让开发者对业界主流的跨端框架, 有了初步认识. 感谢 Taro 团队的付出.
不过横评这件事, 要想得到更精确的结论, 其实非常花费时间. 它需要:
真实的动手写多个平台的测试 demo, 比较各个平台的功能, 性能, 它们的实际情况到底是不是如文档宣传的那样?
真实的学习每个框架, 了解它们的学习曲线, 在实际开发中遇到问题时, 感受它们的文档, 教程, 社区生态和技服能力到底怎么样?
我们 uni-App 团队投入两周完成了这个深度评测, 下面我们就分享下, 实际开发不同框架的测试例时遇到的问题, 以及在各端的兼容测试结果. 在本文里, 我们团队基于真实测试数据及各框架官网可采集到的公开数据, 希望客观公正地评价各个框架的选型和优劣. 但宥于利益相关, 本文的观点很可能是带有偏向性的, 大家可以带着批判的眼光去看待.
评测实验介绍
开发内容: 开发一个仿微博小程序首页的复杂长列表, 支持下拉刷新, 上拉翻页, 点赞.
界面如下:
开发版本: 一共开发了 6 个版本, 包括微信原生版, wepy 版, mpvue 版, taro 版, uni-App 版, chameleon 版(以这些产品发布时间排序, 下同), 按照官网指引通过 cli 方式默认安装.
测试代码开源(GitHub 仓库地址: https://github.com/dcloudio/test-framework https://github.com/dcloudio/test-framework ),
Tips: 若有同学觉得测试代码写法欠妥, 欢迎提交 PR 或 Issus
测试机型: 红米 Redmi 6 Pro,MIUI 10.2.2.0 稳定版(最新版), 微信版本 7.0.3(最新版)
测试环境: 每个框架开始测试前, 杀掉各 App 进程, 清空内存, 保证测试机环境基本一致; 每次从本地读取静态数据, 屏蔽网络差异.
测试维度:
跨端支持度如何?
性能如何?
学习门槛
工具与周边生态
1. 跨端支持度如何
开发一次, 到处运行, 是每个程序员的梦想. 但现实往往变成开发一次, 到处调错.
各个待评测框架, 是否真得如宣传的那样, 一次开发, 多端发布?
我们将上述仿微博 App https://github.com/dcloudio/test-framework 依次发布到各平台, 验证每个框架在各端的兼容性, 结果如下:
测试结果说明:
? 表示支持且功能正常,? 表示不支持, 其它则表示支持但存在部分 bug 或兼容问题
wepy 2.0 宣称版已支持其他家小程序, 本测试基于 wepy 官网指引安装的 wepy-cli 版本为 1.7.3, 尚不支持多端
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, 详见 https://taro-ui.aotu.io/#/
uni-App: 官方提供了 uni ui, 可全端运行; uni-App 还有一个插件市场, 里面有很多三方 ui 组件, 详见 https://ext.dcloud.net.cn/
chameleon: 官方提供了 cml-ui 扩展组件库, 可全端运行, 但组件数量略少, 详见 https://cmljs.org/doc/component/expand/expand.html
最后补充跨端案例:
mpvue: 微信端案例丰富, 未见其它端案例
taro: 微信端案例丰富, 百度, 支付宝, H5 端亦有少量案例
uni-App: 微信, App,H5 三端案例丰富, 官方示例已发布到 6 端
chameleon: 未看到任何端案例
综合以上信息, 本项的最终评测结论: uni-App> taro> chameleon> mpvue> wepy, 原生微信小程序
2. 跨端框架性能如何
跨端框架基本都是 compiler + runtime 模式, 引入的 runtime 是否会降低运行性能?
尤其是与原生微信小程序开发相比性能怎么样, 这是大家普遍关心的问题.
我们依然以上述仿微博小程序为例, 测试 2 个容易出性能问题的点: 长列表加载, 大量点赞组件的响应.
2.1 长列表加载
仿微博的列表是一个包含很多组件的列表, 这种复杂列表对性能的压力更大, 很适合做性能测试.
从触发上拉加载到数据更新, 页面渲染完成, 需要准确计时. 人眼视觉计时肯定不行, 我们采用程序埋点的方式, 制定了如下计时时机:
计时开始时机: 交互事件触发, 框架赋值之前, 如: 上拉加载 (onReachBottom) 函数开头
计时结束时机: 页面渲染完毕(微信 setData 回调函数开头)
Tips:setData 回调函数开头可认为是页面渲染完成的时间, 是因为微信 setData 定义如下(微信规范):
字段 | 类型 | 必填 | 描述 |
---|---|---|---|
data | Object | 是 | 这次要改变的数据 |
callback | Function | 否 | setData 引起的界面更新 < strong ztid="182" ow="48" oh="17"> 渲染完毕 后的回调函数 |
测试方式: 从页面空列表开始, 通过程序自动触发上拉加载, 每次新增 20 条列表, 记录单次耗时; 固定间隔连续触发 N 次上拉加载, 使得页面达到 20*N 条列表, 计算这 N 次触发上拉到渲染完成的平均耗时.
测试结果如下:
说明: 以 400 条微博列表为例, 从页面空列表开始, 每隔 1 秒触发一次上拉加载(新增 20 条微博), 记录单次耗时, 触发 20 次后停止(页面达到 400 条微博), 计算这 20 次的平均耗时, 结果微信原生在这 20 次 触发上拉 -> 渲染完成 的平均耗时为 876 毫秒, 最快的 uni-App 是 741 毫秒, 最慢的 mpvue 是 4493 毫秒
大家初看这个数据, 可能比较疑惑, 别急, 下方有详细说明
说明 1: 为何 mpvue/wepy 测试数据不完整?
mpvue,wepy 诞生之初, 微信小程序尚不支持自定义组件, 无法进行组件化开发; mpvue,wepy 为解决这个问题, 将用户编写的 Vue 组件, 编译为 WXML 中的模板(template), 变相实现了组件化开发能力, 提高代码复用性, 这在当时的技术条件下是很棒的技术方案.
但如此方案, 在页面复杂, 组件较多的时, 会大量增加页面 dom 节点数量, 甚至超出微信的 dom 节点数限制. 我们在 红米手机 (Redmi 6 Pro) 上实测, 页面组件超过 500 个时, mpvue,wepy 实现的仿微博 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-App,taro 都在调用 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-App,taro 相比微信原生, 性能差距并不大.
这个结果, 和 web 开发类似, Web 开发也有原生 JS 开发, vue,react 框架等情况. 如果不做特殊优化, 原生 JS 写的网页, 性能经常还不如 vue,react 框架的性能.
也恰恰是因为 Vue,react 框架的优秀, 性能好, 开发体验好, 所以原生 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 > 微信原生开发未手工优化, taro> chameleon>> wepy> mpvue
3. 学习门槛
DSL 语法支持度
主流跨端框架基本都遵循 React,Vue(类 Vue)语法, 其主要目的: 复用工程师的现有技术栈, 降低学习成本. 此时, 跨端框架对于原框架 (React/Vue) 语法的支持度就是一个重要的衡量标准, 如果支持度较低, 和原框架语法差异较大, 则开发者无异于要学习一门新的框架, 成本太高.
实际开发中发现, 各个多端框架, 都没有完全实现 vue,react 在 Web 上的所有语法:
taro 对于 JSX 的语法支持是相对完善的, 其文档中描述未来版本计划,
更多的 JSX 语法支持, 1.3 之后限制生产力的语法只有只能用 map 创造循环组件一条
mpvue,uni-App 框架基于 vue.js 核心, 通过修改 Vue.JS 的 runtime 和 compiler, 实现了在小程序端的运行, 支持绝大部分的 Vue 语法; uni-App 编译到微信端曾经使用过 mpvue, 但后来重新编写, 支持了更多 vue 语法如 filter, 复杂 JavaScript 表达式等;
wepy,chameleon 都是 类 Vue 的实现, 仅支持 Vue 的部分语法, 开发时需要单独学习它们的规则;
DSL 语法支持评测: taro,uni-App> mpvue> wepy,chameleon
学习资料完善度
官方文档, 问题搜索, 示例 demo 的完备度方面:
wepy: 文档只有 2 页, 也无需搜索. 仅支持微信, 所以组件 API 等文档都直接看微信的文档. 没有提供示例 demo. 详见 https://tencent.github.io/
mpvue: 文档较少, 但其概念不复杂, 也没有支持 H5,App, 所以组件 API 等文档都直接看微信的文档, 学习难度低. 问题搜索效果一般. 没有提供示例 demo. 详见 http://mpvue.com/
taro: 基础 API 文档完整, 具体使用问题资源较少, 问题搜索效果一般, 示例 demo 只包含基础功能, 仅发布了微信一端. 详见 https://taro.aotu.io/
uni-App: 基础文档和各种使用专题内容丰富, 问题搜索效果较好, 示例 demo 功能完备, 并发布为 7 端上线. 详见 https://uniapp.dcloud.io/
chameleon: 基础 API 文档完整, 具体使用问题资源较少, 问题搜索效果一般, 示例 demo 只包含基础功能, 仅发布了微信一端. 详见 https://cmljs.org/
教学课程方面:
学习资料完善度评测: uni-App> mpvue , taro> chameleon> wepy
技术支持和社区活跃度
开发难免遇到问题, 官方技术支持和社区活跃度很重要.
本次评测 demo 开发期间, 我们的同学(同时掌握 vue 和 react), 在学习研究各个多端框架时, 切实感受到由于语法, 学习资料, 社区的差异带来的学习门槛, 吐出了很多槽.
综合评估, 本项评测结论: uni-App> taro> mpvue> wepy> chameleon
Tips: 本测评忽略 React,Vue 两框架自身的学习门槛
4. 工具和周边生态
工具
所有多端框架均支持 cli 模式, 可以在主流前端工具中开发.
各框架基本都带有 d.ts 的语法提示库.
由于 mpvue,uni-App,taro 直接支持 vue,react 语法, 配套的 ide 工具链较丰富, 着色, 校验, 格式化完善, chameleon 针对部分编辑器推荐了插件, wepy 的有一些三方维护的 vscode 插件.
工具属性维度, 明显高出一截的框架是 uni-App, 其出品公司同时也是 HBuilder 的出品公司, DCloud.io https://dcloud.io/ .
HBuilder/HBuilderX 系列是四大主流前端开发工具(可对比百度指数), 其为 uni-App 做了很多优化, 故 uni-App 的开发效率, 易用性非其他框架可及.
当然对于不习惯 HBuilderX 的开发者而言, uni-App 的这个优势无法体现.
周边生态
一个底层框架, 其周边配套非常重要, 比如 ui 库, JS 库, 项目模板.
wepy: 出现时间久, 开源项目多, 占据一定优势.
mpvue: 发布时间也较早, 历史积累较多.
taro: 官方提供了 taro ui,GitHub 上有一些开源项目. 不过 taro ui 只支持小程序和 H5, 不支持 App 端
uni-App: 提供了插件市场 https://ext.dcloud.net.cn/ ,ui 库, 周边模板丰富
chameleon: 还没有形成周边生态.
值得注意的是, uni-App 和 mpvue 的插件生态是互通的, 都是 vue 插件. 所以双方还联合举办了插件大赛. 这个联合生态的周边丰富度, 是目前各个框架中最丰富的.
综上比较, 工具和周边生态评测结论: uni-App,mpvue> wepy> taro> chameleon
其他常见评测指标
GitHub star:
GitHub star 数对比: taro> wepy>mpvue> uni-App> chameleon
Tips:
star 数采集时间: 2019.04.08 16:30
百度指数
百度指数代表了开发者的搜索量和包含关键字的网页数量. 如下是各跨端框架近 7 天 (2019-03-24 ~ 2019-03-30) 的百度指数:
Tips:
wepy 未被百度指数收录, 说明其搜索量和包含该关键字的网页数量都不够多.
可以看出一个较大的冲突就是 uni-App 的 star 数量较少, 而百度指数较高.
根据我们分析, star 数量和产品发布时间有关, 也和用户使用习惯有关. 大多框架的交流互动主要是 GitHub 的 issus, 而 uni-App 的开发者在其问答社区 https://ask.dcloud.net.cn/ 交流, GitHub 页面访问量较低. 另外我们观察了一周的 star 的增速, 每周 star 新增量, uni-App 是最多的.
案例
我们对比了每个框架公布的案例, 如下的框架名称的超链接已指向其案例页面, 可以直接访问.
仅看发布到微信小程序的案例, 数量和质量综合对比, https://tencent.github.io/wepy/> https://github.com/Meituan-Dianping/mpvue> https://github.com/NervJS/taro , uni-App https://uniapp.dcloud.io/case> chameleon
如果看多端案例, 综合对比, uni-App https://uniapp.dcloud.io/case> https://github.com/NervJS/taro> https://github.com/Meituan-Dianping/mpvue> https://tencent.github.io/wepy/> chameleon
wepy: 的知名案例较多, 包括很多一线互联网公司.
mpvue,taro: 跨端框架的出品方本身为一线互联网公司, 其内部项目会使用这些框架, 经受过实战考验. 除内部项目外, 暂无其他一线互联网公司使用.
uni-App: 案例很多, 官方数据已经超过 10w+. 但以创业者和政企单位为主, 暂无一线开发者使用.
chameleon: 未找到案例, 无法参与本评测.
其他补充说明
1. App 侧的补充说明
目前有 taro,uni-App,chameleon 三家框架支持 App 端. 但在 App 端大多是三方产品, 比如 taro 使用 expo(一个基于 react native 的封装库),chameleon 使用 weex.
不管 react native 还是 weex, 其架构与小程序架构完全不同, 从排版到 API 能力都差别很大, 所以这类产品跨 App 端时兼容性较差.
uni-App 的 App 端, 内置一个完整小程序引擎, 并补充了可选的 weex 引擎给对性能要求更高的开发者. 这也是 uni-App 在 App 端能够正常运行微信小程序代码的原因.
整个业内目前还不存在一个完全开源的小程序引擎(微信, 百度, 支付宝, 头条的小程序引擎源码均未开源).uni-App 的小程序引擎不是全开源, 而是能力层开源, 中控未开源.
所以可能各家的多端框架, 在 App 端都有不完美的地方, 需要开发者使用时注意.
其实 App 引擎并非前端领域, 是原生领域的另一个竞技场. 后续 uni-App 会再出一个与 cordova,react native,weex,flutter 的横评.
2. 转换和混写
taro 提供了原生小程序转换为 taro 工程的转换器, 也支持在原生小程序里部分页面嵌入 taro 编写的页面. uni-App 和 chameleon 提供了转换的文档, 没有转换工具.
结语
真实客观的永远是实验和数据, 而不是结论. 不同需求的开发者, 可以根据上述实验数据, 自行得出自己的选型结论.
但作为一篇完整的评测, 我们也必须提供一份总结, 虽然它可能加入了我们的主观感受:
如果你只开发微信小程序, 不做多端, uni-App 仍然是最好的选择, 除非你有兴趣手动优化原生小程序的代码, 或者对 react 非常熟悉不愿意学习 vue 也可以使用 taro.
如果你主要为了统一各家小程序, uni-App 仍然是最好的选择, taro 次之.
如果你还需要跨端到 H5 侧, 那么 uni-App 是最好的选择.
如果你还需要跨端到 App 侧, 那么 uni-App 是唯一可商用的选择.
当然, uni-App 也距离完美尚远, 只是在参比框架中相对有优势. uni-App 团队也仍继续大力投入, 持续填坑, 帮助开发者提升投入产出, 提升开发体验!
如有读者认为本文中任何评测失真, 欢迎在这里报 issuse.
来源: http://www.bubuko.com/infodetail-3034206.html