Taro 已经 100% 支持转换京东小程序,受到了很多同学的关注。当中有欢呼雀跃的声音:“一键转换为京东小程序,终于可以准时下班啦”。也有对 Taro 不太了解的同学提出了一些疑问:“转换的效果如何?”、“转换后代码的性能是否达标?” 等等。
针对各种疑问,我们从性能与开发体验的角度切入,把京东小程序原生开发与 Taro 开发进行了一番对比。
性能对比
针对性能的问题,我们分别测试了 Taro 空项目的包大小和 Taro 在长列表中的表现。因为包大小会影响小程序的首次加载速度,而长列表则是常常出现性能瓶颈的场景。
Taro 空项目包大小
目前各小程序都有对主包的大小进行限制,如京东小程序限制为 5M、微信小程序限制为 2M。这是因为初次进入的速度对于用户的体验非常地关键,而主包体积越大下载的时间就最长。因此小程序框架的大小也成为了开发前框架选型的重要参考指标之一,倘若框架体积过大,就会压缩业务逻辑的可用空间。
下列图片分别是 Taro 运行时框架压缩前后的大小,可以看到压缩后仅为84k,对主包空间的影响十分小。
压缩前:
压缩后:
长列表渲染表现
benchmark 介绍
我们参照 js-framework-benchmark 编写了一份 benchmark,测试对比了 Taro 代码与原生代码在长列表场景下的渲染表现。
测速指标
-
初始化:从进入页面开始到完成 40 个商品的渲染。
-
创建:页面 onLoad 后创建 40 个商品。
-
增加:往已创建了 40 个商品的列表中每次增加 20 个商品。
-
部分更新:在 400 个商品中更新每第 10 个商品的名称。
-
交换:在 400 个商品中交换其中两个商品的位置。
-
选中:点击商品图片,改变商品名称的字体颜色。
计时点
Taro:
开始:事件响应函数的顶部。
结束:setState
回调函数的顶部。
原生小程序:
开始:事件响应函数的顶部。
结束:setData
回调函数的顶部。
其它
benchmark 仓库:Github
Taro 版本:1.3.21
测试机型:魅蓝 note
测试方法:每组测试 10 条数据,去除其中最大值与最小值后求平均值
测试结果
因为在京东小程序与微信小程序中,setData 的 callback 的触发时机稍有不同,所以分开列出。
操作 | Taro jd | 原生京东小程序 |
---|---|---|
初始化 | 150 | 123 |
创建 | 87 | 85 |
部分更新 | 125 | 235 |
交换 | 140 | 213 |
选中 | 131 | 155 |
操作 | Taro weapp | 原生微信小程序 |
---|---|---|
初始化 | 1155 | 1223 |
创建 | 500 | 408 |
部分更新 | 167 | 307 |
交换 | 252 | 309 |
选中 | 193 | 178 |
经测试发现,列表的长度会对增加操作的耗时产生影响:列表越长,增加操作的耗时越久。因此不能简单地对 N 次增加操作求平均增加耗时。这里我们选择使用折线图来展现出随增加操作次数的变化,渲染耗时的变化趋势。
测试结论
创建
在创建时,Taro 会对数据做一些处理,因此会比原生稍慢。
初始化
初始化与创建相比,差别是引入了页面构造耗时。即初始化耗时 = 页面构造耗时 + 创建操作耗时。
Taro 在页面初始化、创建操作时都会对数据进行处理,因此整个初始化耗时会比原生稍慢。
那为什么微信小程序中 Taro 初始化耗时更短呢?在 benchmark 中 Taro 和原生分别在 componentWillMount
和 onLoad
渲染列表,而 Taro 使用 Component 构造页面,componentWillMount
其实是在 attached
生命周期中触发。因为在微信小程序中 attached
比 onLoad
早触发得多,所以会出现如此现象。
选中
因为 Taro 只是把回调函数包装了一层,处理了事件参数和 this 等,所以和原生的速度相当。
部分更新、交换、增加
Taro 的速度会优于原生。原因是 Taro 会先对将要 setData 的数据和当前 data 的数据做一次 diff,这能够大大减少 setData 的数据量,加快渲染速度。对比两个折线图可以得知,数据量越大,diff 的优化收益也越大。
Taro 对小程序的性能优化
setData
在小程序中,性能的问题主要在于单次 setData 数据量过大和频繁调用 setData 上。Taro 利用 diff 解决了单次 setData 数据量过大的问题,而对于频繁调用 setData 也有解决的办法。
Taro 的 setState 遵循 React 规范,不同于 setData 的同步更新,它会异步地去更新视图。因此假设开发者在单次事件循环中多次调用 setState,最后也只会在下一个事件循环中进行一次 setData。
跳转预加载
小程序由 A 页面跳转到 B 页面的过程中,从 A 页面发起跳转到 B 页面触发 onLoad,有着 300~400 毫秒的延时。Taro 提供了 componentWillPreload
钩子,钩子会在发起跳转后立即执行。开发者可以尽早地在钩子里做一些数据拉取的工作,相比在 onLoad 触发后再去拉取数据就能够节省 300~400 毫秒的延时。
shouldComponentUpdate & Taro.PureComponent
开发者的 Class Component 可以继承 Taro.PureComponent
,这样组件在更新前会对新旧 props 和新旧 state 各做一次浅对比,避免不必要的更新。当然开发者可以自己实现 shouldComponentUpdate
,通过手动控制新旧 props 和新旧 state 的对比,决定是否更新组件。
Taro.memo
如果开发者书写的是函数式组件,则可以利用 Taro.memo
实现 shouldComponentUpdate 的相同功能。
开发体验对比
语法
京东小程序的原生语法和微信小程序相仿,都是类 MVVM 语法,没有接触过小程序的开发者有一定学习成本。另外样式语法为 css 的子集,其中自适应尺寸单位为 rpx,这样意味着如果我们需要 css 预处理器时需要手动配置工作流,并且在编写样式时处处注意尺寸单位的转换。
目前 Taro 遵循 React 语法(将来会支持所有 Web 前端框架),JSX 令我们的代码更加灵活。因此拥有 React 开发经验的开发者可以马上上手 Taro 的开发工作。在样式方面 Taro 支持在创建项目时选择是否使用 css 预处理器,选择后会自动配置相应的工作流。对于样式单位 Taro 也会把用户编写的 px 数值自动转换成对应的 rpx 数值,开发者无需再分心处理各平台的样式单位。
项目结构
原生开发中,页面和组件各由4个文件(js、jxml、jxss、json)所组成,代码管理相对麻烦。
Taro 中页面和组件均由一份 js 文件和一份样式文件组成,创建与维护十分容易。
开发生态
微信小程序经过不断迭代,相继推出了插件系统和支持引用 npm 包的功能。但京东小程序暂不支持前两者,京东小程序社区也还没打造起来,开发生态资源十分匮乏。
Taro 中不但能*引用 npm 包,而且还大量支持 React 社区中沉淀的优秀工具和库,如 react-redux、mobx-react 等。
开发辅助
京东小程序原生开发不支持 Typescript,只能在 IDE 的编辑器中有自动补全功能,编码效率不高,同时也容易出错。
Taro 完美支持 Typescript,自带代码智能提示和代码实时检查功能,能让开发效率大大提升。
写在最后
看到这里大家可能会问,Taro 性能真的优于原生吗?其实并不然,针对每个场景,我们都可以用原生写出性能最佳的代码。但是这样做工作量太大,实际项目开发中需要掌握效率与优化之间的平衡。Taro 的优势在于能让我们在书写更有效率的代码、拥有更丰富的生态的同时,还带来了不错的性能。
最后,欢迎大家来使用 Taro 开发各端应用,有任何开发问题或合作意愿请联系 taro@jd.com,我们会第一时间回复。
相关链接