我最近在布莱顿的FFConf大会上说了句话:“你应该用这个,就用这个!就没有比他更好的了!”。所以在这篇文章里,我依旧要做同样的吹捧行为,和大家聊聊在手机应用上使用各种流行框架的代价。

使用框架的好处

今年早些时候我写了关于React性能的文章,结果回复越来越多,过滤有效信息就花了我很长时间。回复的内容也是千奇百怪,有赞赏的,有提供意见的,也有极端宗教主义的。当然,最终我还是得到了更有价值的见解,那我现在就试着总结一下适用于所有框架(在某种程度上)的一些通用的看法:

  • 框架用着很有趣。我相信,没有谁会一直去用不友好的框架吧,大家都那么忙是吧。所以,毫无悬念,框架用着舒服对于我们来说,是最重要的。
  • 使用框架会让你的产品构建得更快。这一点很重要,特别是对于小型的初创公司来说,有一个直接拿过来用的框架去搭建你自己的产品原型,就跟有船没船一样,难道你还要自己造船啊,买一艘好不好。(开源的不花钱哈哈
  • 使用框架会更加稳定。早先的前端都很痛苦,还可能在处理IE5和IE6的兼容性BUG,还有更早版本的Firefox、Safari,当然还有Chrome。不过呢现在好多啦,浏览器过去几年来积累了一些不错的标准。:)
  • 如果你熟知某个框架,那你将能得到更多的职业认同。比如你想找工作,跟面试官说你熟知最新的或最了不起的框架,那可不得了。

根据各种回复,我汇总成了一句话就是:对于开发人员而言,最重要的还是框架给他带来的舒适感。【译者:原文是 Ergonomics(人体功效学)生涩不已,则改为舒适感。】

重要的事情我要再说一遍,对于开发人员而言,最重要的还是框架给他带来的舒适感。那怎么解读“舒适”二字,按照我的理解,那感觉就像“如果框架好用的话,我就能分分钟创造出用户想要的东西来”。嗯……这个从表面来看很吸引人,但我认为我们还需要从用户需求这个根本的点上去讨论下。

开发舒适度 vs 用户需求

说到底,开发者的存在是因为用户有各种不同的需求。以下是用户针对于APP比较关心的事情:

  • 网站和APP应该快速展现到用户的眼前。
  • 它要有更顺畅的交互。
  • 它不应该让我手机变慢。
  • 它不应该用着用着就崩溃掉了。
  • 它应该具有我想要的功能。

针对以上的情况,我们很快就坠入鱼和熊掌的漩涡:一方面我们想使用框架方便快捷的去进行开发,另一方面我们还需要满足用户需求。不管你想不想,这都是一件开发人员取舍的事情。归根结底,使用框架,是要付出一定成本的。

相关前提

这里要说一下,类库或工具库我不想把它们纳入讨论范围。至少在我看来,你不能把它当做框架来看待,它如果有问题的话我们可以很快找其他的库来将它替换掉。不喜欢这个日期格式化的库?没问题,我们再找一个好用的。但框架,就很难换掉了,换框架,基本上就是重写程序,所以从量级上来说两个的区别就很明显,框架要大的多,涉及的层面也多得多,以至于选型也是一件很重要的事情,一定要慎重。

代码成本

所有的代码都有使用成本的,但我认为,有些特定的成本是专属于框架的。比如:

使用框架的代价0

上面的提示是说你使用的某些方法被弃用了,尽快更新为新的方法吧。非常奇怪。

  • 学习成本。 你必须花时间学习这个框架:学习他为什么要这样写代码,为什么要定义“idiomatic”这个关键字;学习它的模板、用例、运行方式。这和学习原生框架本身没什么两样,我们只是把一组问题换成了另一组。
  • 二次学习成本。 有时候你正在磕磕绊绊地开发着你的应用,然后你在控制台上看到一个警告,告诉你需要弃用什么,然后你要更新你的代码。框架的新版本来了,你要重新学习新版本,也就意味着你的项目可能要为框架的新版本重新开发一下了。
  • 调试成本。 框架正如任何其他软件一样,也有BUG。如果是写原生代码,那你修BUG肯定不会有什么太大问题。但是想要补一个框架的BUG,就可能非常难了,甚至是根本不可能的。如果发现了问题,你可能需要具备科学怪人般的钻研精神,然后像个疯猴子扒心扒肺的查找和调试,直到真正的解决办法出现。

除了开发的成本,用户也要为此而支付代价:

  • 时间成本。 启动我们的APP需要多长时间?
  • 带宽成本。 APP运行需要用掉多少带宽?
  • CPU使用情况(电池)。 它的CPU利用率如何?会不会很耗电。
  • 流畅度。 用户喜欢顺畅的体验,那代码对屏幕的更新情况如何?
  • 内存使用情况。 它占用内存多不多?会影响到其他程序运行吗?会让手机崩溃吗?

把数据摆到台面上

以上述讨论为基础,我想做一些测试,从而能够从数据中得到一些有用的结论。

我决定先测试下各个常用框架的启动时间。我的想法是给出一个用各种框架搭建起来的同一应用,然后看各框架启动所需花费的时长。我选择使用TodoMVC来测试,因为在我看来,它是一个MVP网页应用,而从用户角度来看,功能上都一样,都可以完成他的需求。

使用框架的代价1

TodoMVC:我的各框架启动时间测试用例

启动时间 / 初始化交互逻辑

我想看看在Nexus5和iPhone 5S上启动某些框架需要的时间、带宽和CPU使用情况。其实就是各框架执行JavaScript所花费的时间。

使用框架的代价2

测试方法

我用 WebPagetest 的Nexus5 装载页面,对每次运行我得到Timeline,然后我把Timeline文件传给Big Rig 来处理。iPhone的测试结果是我自己做的,这个只能手动,因为Safari的Javascript性能分析好像还不支持任何追踪输出。

使用框架的代价3

使用Big Rigg快速评估每个框架的TodoMVC启动时间。

顺带提一句,这就是我创建Big Rig的原因。我想让大家可以更容易地快速处理这种数据。

重复测试

如果你想自己做类似这样的测试,比如说在使用Chrome的设备上运行用例,你可以按照下列步骤操作:

  • 安装Big Rig CLI: npm install -g bigrig
  • 去 WebPagetest.
  • 把地址设定为 Dulles。
  • 把浏览器设定为 Nexus 5 – Chrome (或 Beta/Dev)。
  • 在Chrome设置项下,点击 “Capture Dev Tools Timeline”。
  • 运行测试。
  • 在得到的结果中,下载Timeline文件。
  • 运行 bigrig --file /path/to/timeline.json --pretty-print.

如果你愿意,你可以通过视频观看我怎样从WebPagetest上取得Timeline文件的:

结果显现

以下是我对各种框架的测试结果:

框架 大小 N5的启动时间 iPhone 5S的启动时间
Polymer v1.1.4 41KB5 409ms 233ms
Polymer v1.2.2 47KB5 155ms 232ms
AngularJS v1.4.3 324KB 518ms 307ms
React v0.13.3 [JSX not transformed] 311KB 1,201ms 1,463ms
React v0.13.3 [JSX transformed via Babel]4 162KB 509ms 282ms
React v0.13.3 [JSX transformed; prod build]4, 6 160KB 174ms 118ms
Backbone v1.2.2 [inc. jQuery & Underscore] 139KB 248ms 168ms
Ember v1.10.0-beta.3 580KB 1,992ms 1,440ms
Vanilla 16KB 50ms 33ms
  1. 在Nexus5上用Chrome 47进行的运行测试。
  2. 在iPhone 5S上用Safari 9进行的运行测试。
  3. 所有启动时间均包括处理初始数据的时间。
  4. React 分为JSK未转换和已经过Babel转换的版本。
  5. 排除Web Components Polyfill(12KB)。
  6. React 分了几个版本,也包括未压缩的版本和已压缩的版本。

对于我来说结果已经非常清楚了:在手机上使用框架真的很沉重,尤其是对比使用原生Javascript来看。最快的是Polymer 1.2.2,这个超级赞,但比起原生Javascript来它还是慢了三倍。 React和Polymer非常相似,但从我另外一篇关于React性能的文章综合起来看,我觉得还是有些问题的。

为了让大家看数据更清晰,大家有几项需要注意的点:

  • TodoMVC不能直接把JSX转成React,所以我自己转了一下。 为公平起见(因为JSX转换运行时间非常长),我又加了一种更贴近于“生产环境”的版本,然后也对它进行了测试,它并非压缩版的React,因此也有区别,这就形成了表格中的React三个版本。
  • 上述时间不包含转换时间。 我所唯一所测量就是在JavaScript中启动框架的时间,然后得到一些初步观点。事实上,有些的框架还不是压缩版本。关于更多关于框架转换规格的探讨,去找一下Filament组织去年的帖子。

反对意见

我猜对于这个测试可能大家会有一些反对意见,简单说下:

我觉得你的项目可能比TodoMVC的模式要复杂和费时的多。

  • “TodoMVC模式并不流行”。我已经调查过了,调查中我了解了大部分都是这个模式,如果不是的话,会有架构师来调整成MVC模式。
  • “TodoMVC并不能代表我的项目”。这可能是事实,但我也可以说你的项目可能比TodoMVC还要费时。Paul Irish最近对Reddit的手机端做出一个性能审查,其中之一就是启动手机上React组件的时间是22秒!
  • “我们用户不用Nexus 5 / iPhone 5S。” 这没关系,我也更倾向于使用比较好的硬件。但数据表明大部分手机用户并不会使用太高端的手机,因此我更觉得此等情况不容乐观。
  • “新版的肯定会好一些的”。这可能是事实,但这对你现在使用的版本并没什么帮助。

价值六十万美金的问题

因此,不可避免的,你得面对这个问题了,“你应该用框架去做APP吗?”

我无法回答这个问题,我认为这完全取决于你的选择。你认为你需要使用框架的理由可能有一百万零一个。但对于值不值得,我的想法是:

  • 框架作为一种设计模式或一种创意,是没问题的。框架是理解哪种办法可行的关键部分,而这最终会体现在系统平台层上,它是驱动技术革新的重要环节。
  • 框架是一种反向控制机制。作为函数类库你可以随时把它干掉,但是框架反向控制着全局,它控制着此应用的整个生命周期。虽然你可以写你的代码,你仍要为你的功能实现负责,但运行时的过程,已经不再你的控制之中了。
  • 对于我来说,手机上的前端框架费时严重,至少比起原生代码而言是这样的。

用原生代码写功能本身就是最长远有益的选择。

当我看框架时我看到了什么,我看到的是开发效率(是的,这是最重要的,我同意这点)但我禁不住会想,对于大多数开发人员来说,用原生代码写功能本身就是最长远有益的选择。铁打的WEB,流水的框架,正如我前面说到的,框架确实可以贡献创意和设计模式。但一旦你发现你现在用的框架已经不合适你的项目了,或有个漏洞一直解决不了,你最终还是要依赖原生代码的。

更多信息

今年早些时候我写关于React的帖子时,我说:

在我看来,舒适开发固然很重要,但应该还是以我们的用户需求为中心。

现有我仍然这么认为。尽管我也希望能让自己的生活过的更加美好,可我不想我的APP在用户手里出现问题,我也不想让用户来因此而付出更多的代价。但现在,我深表顾虑。

我担心使用框架在手机上会有更多的问题。

当然,我的测试仅仅是第一步。除了启动还有很多其他的点,这里我没有更详细去检测,比如:对内存使用情况 、长期CPU使用情况、流畅度的影响等等。总体而言,我认为我们还有很多工作要做。

如果我们能做出启动快速、内存占有少、运行顺畅的框架,同时又兼具自己的开发效率和舒适感,那我们就离成功不远了。到那时候,或这个时候,至少在手机方面,我会忠于原生代码。

余下全文(1/3)

本文最初发表在微信公众号,文章内容属作者个人观点,不代表本站立场。

分享这篇文章:

请关注我们:

发表评论

电子邮件地址不会被公开。 必填项已用*标注