微信扫描登录

从 Web 前端到客户端
作者:rank

最近工作变化较大,除了管理一个独立的产品业务外,还负责了美团 Web/iOS/Android平台业务研发。

就在大约 4 个月前,我接手了美团大平台的大前端工作。包括美团客户端 App,Web 端的平台业务,还包含美团各端的基础设施研发工作。也正式开始了 Web/iOS/Android 的大前端路。也许很多垂直业务团队和小型创业公司现在已经是这种大前端模式了,但平台+基础设施是比较大的团队(小一百人规模)还比较少见。所以现在这模式也算是一种探索吧。

在这篇文章里,我分享一下管大前端后的一些技术及管理心得。

一、先泼 React Native 冷水

我此前虽从事过 Windows 和后端开发,但专业领域还是在 Web 前端最久,所以我首先想分享给 Web 前端同学的是,虽然现有 React Native(RN) 类似的跨端技术方案,「似乎」RN 有一统天下的意思,但实际各公司生产环境里还都在试水,各端仍相对是独立研发的状态。

简单列几个主要问题:

  1. RN 质量问题,某些异常和 Crash 无法解决。要解决就必须吃透 RN 底层,对于研发团队来说技术质量不可控,这是个致命的问题。

  2. 两周一个迭代,维护升级成本高。问题根源还是源于「质量」,所以才会如此快地迭代。要在生产环境下用,意味着需要投入大量时间在追新版本;或在某个版本进行持续维护。这需要拿出额外的研发人力每两周合版保证 RN 质量。于是就有一定的拆衷方案,就是在交互复杂或表现细致的地方不做那么「细腻」。还有一种方案也就是 Weex 的办法,不能控制 RN,宁可自己造一个 RN。

  3. 无杀手级应用背书。据我所知至今还没有一个「知名」「用户端」「商业」App 完全用 RN 开发并超过半年以上。http://facebook.github.io/react-native/showcase.html 这个链接里收集了使用 RN 的案例,除 FB 外都是部分功能使用 RN。

这三个问题决定了成熟的商业产品不会轻易用它开发,只用于用户端少数几个刚需高频更新功能。到目前为止,线上我们实验结果已经将它逐渐下线转而采取了其他方案;RN 也目前还在偏企业侧的 App 应用里,但仍有些 Crash 解决起来很费劲。

我之前也在「微博」上提到了:

就目前 RN 的情况,最好不要大面积在 C 端产品上用。— 这是几千万日活 App 在此实验的经验。

从最早桌面时代到移动时代,跨端开发技术都有场景受限的历史(参看 Qt)。要实现跨端理想还有很远的路要走,这决定了在不同端上专业差异还比较大。

二、客户端的不同

客户端相比 Web 端不同,是客户端可以近一步拿到更底层的控制权。

1. 控制请求与资源管理

站在 Web 开发的角度,能控制「请求」一直是件梦寐以求的事。在 HTTP 2 之前,请求是 Web 性能的第一杀手。在客户端,可以劫持所有请求都通过长链接来解决请求并发性能下降的问题。这不仅仅是简单的性能提升,还可以解决 DNS 被劫持的问题(对于国内环境域名被劫持实在是太常见了)。长链从根本上解决 HTTP 连接成功率的问题,这类技术在 BAT 也很成熟并广泛应用。

2. 浏览器增强

由于 W3C 标准严重滞后于时代,加之各浏览器厂商的标准与实现不一,导致各公司桥、容器满天飞。同时这也是 Web 开发者熟悉的领域。说一个不好解决的问题吧,如果一个公司共用一个桥,如何定义什么是基础桥容器下沉,太灵活,业务方就相当于 fork 一份出去,未来不能再收拢,如果都由桥容器所在的平台组来做,响应能力是个问题。什么时候由业务方来做,这是个难点。

3. 跨端全局视角

单纯在 Web 端立场,希望 Web 思想一统天下把同构做到客户端去;站在所有端立场去看问题时,却大不一样。也可以说是屁股决定脑袋。

我还是拿大家较熟悉的 RN 来举例(并不限于此)。用传统的 MVC 分层(Model,View,Controller)来理解 RN 是一种解决跨端组件化、快速发版、高性能的 垂直纵切「切洋葱皮」 MVC 的方案。

那有没有其他解决思路呢?

对大型的 App 里模块化,有成熟的包管理与二进制集成的方案集成,开发单独方面复用与协作效率能得有效解决;随着移动设备性能提升及 4G 普及,大多对及时性与试错项目可通过 Web 与 Hybrid 来解决;还有一类就是既对体验有极致要求,还有界面高频变换的场景,可以横向「剥洋葱皮」来解决界面(View)层多变问题。

通过开发一个内置 Native 的 DSL 模板语言,用 RN 的子项目 css-layout 做渲染,也能很方便地做到界面灵活可变的业务场景(甚至有人改造 WebCore 渲染 View 从而实现跨端布局)。

就 RN 解决的领域问题,用全端研发视角,客户端模块化+Web Hybrid离线化+客户端视图层模板化也是办法之一。但需要几个端一起推进协作,所以这也可以算作是前端背景的 Leader 管理大前端的优势之一。

三、客户端的不足

1. 不能实时更新

相对 Web 端,客户端的缺陷是什么呢?首要问题就是由于手机操作系统的限制而不能实现快速实时更新。不能实时更新就意味着在测试周期往往比 Web 要长,但现在业务竞争这么激烈,就会有高速的 App 发版周期。App 涉及业务与团队越多,项目的协调与控制成本就很高。现在的 App 开发周期一般是 3 周发版(也有滚动双周发版的),这样一来业务上的开发时间就很短了 (1 周多),所以业务框架如何实现多人快速开发就成了一个热门的议题,于是各种 MVVM 与模块化的框架就出现了。

由于不能快速更新,衍生的问题之一就是客户端版本分布较为碎片化,与传统的桌面端软件存在同样的问题。一般需要维护 6 个左右的客户端版本。客户端的碎片就意味着服务端数据接口也有版本的概念。给后端带来的困扰是有时一不小心后端改动一个数据结构,客户端就因为接收数据的代码防御没做好造成异常或 Crash 了。

不能实时更新,使得客户端与 Web 端的质量 benchmark 标准也就不同了。

2. 质量控制标准

客户端质量里最重要的技术指标之一就是 Crash 率,通常计算方式为:Crash 数量/DAU(日活)。一般 C 端大型(千万级) App Crash 率 iOS 在 1‰ 以下,0.5-0.8‰;Android 1‰ 左右。

要保证质量,在测试时除了传统 QA 的黑白盒测试外,还需要用到云测、众测等手段解决机型碎片和测试团队可能无法覆盖到的边界问题。也衍生一些枚举测试点击的自动化测试工具(Monkey 等)和流程测试工具。

线上总有漏网之鱼的 Crash 和异常,所以线上要及时 bugfix,客户端又由于操作系统的限制不允许动态下发可执行代码,所以 bugfix 也成为近两年研究的热门技术之一,熟称 Hotpatch(热补丁)。我认为就光这个领域都可以写本书出来。

Android 体系开放,很多人利用系统 Hack 实现了 Hotpatch,但系统兼容性不太好,一旦升级封死了,这口子也就没了。我们做了 Robust 项目,利用 Instant Run 技术,在运行时字节码里加入 Hook,实现 Java 在运行时的 AOP 的 Hotpatch(美团博客已发布)。

iOS 当前最流行的就是 JSPatch 了,JSPatch 作者在自己博客上非常清晰地讲述了实现的思路,这里不赘述。

可以这么说,现在都是利用现有语言或系统特性,甚至 Hack 来实现 Hotpatch,并非系统自带,或多或少还有坑,这就没有 Web 那么完美了。反过来说,这也是 Web 架构的优势所在。

3. 持续集成的重要性

持续集成(CI)对 Web 端没有严格要求,而客户端是必须用持续集成解决很多效率问题。

iOS 与 Android 不同的是,需要用到 Apple 专用机器 —「垃圾桶」Mac Pro。(就是像圆桶一样,没显示器还很贵的主机),iOS 开发团队通常是拿来做持续集成和 Daily build 编译的容器。

利用 CI 做什么呢?静态扫描,发现些代码防御问题,还可以检测包大小,滥用 Lib 库问题。还可以集成之后 Daily build 做 Monkey 与固定 case 的流程自动化测试。自动出持续集成测试的报告,能在人工介入前就发现问题,提高研发效率。如果 App 很多,还需要排队编译。所以如何编译效率与动态扩容又是个问题。

四、Web 端的位置

现今不少人认为「Web 前端」在移动设备时代只是配角,特别是做了很久 Web 前端的老江湖(注意:纯 Web 前端,不包含后端的 Node.js)。这个「配角」观点是基于移动端增长强势弱化了 PC 端地位;其次很多用户侧的移动页面都导流到客户端了;再就是产品主要功能是用客户端技术来开发。

基于全面移动化的角度,我对以上观点是持赞同态度的。所以我一早就提出了 Web 前端的发展需要更全面 T 型人才,也认为是从事 Web 前端多年之后的必经之路。

T 型如何理解?一类是某个端专业,也懂其他端,是跨端人才;另一类是 Web 前端不错,做 full-stack(全栈)开发。

在跨端开发上,Web 前端在「用户体验」与「界面布局」方面有优势。一方面是客户端的同学通常是毕业生或转型而来,较 Web 前端少了「Web 重构」这个年代,而 Web 重构是较为关注 UI 图的还原以及交互及体验。而客户端上 iOS 是传统 C 转型,Android 是后端 Java 转型。

普遍看,客户端工程师比从事 Web 前端的工程师系统底子要好,但对用户体验的理解没 Web 前端工程师了解。像对动画、体验等细节的敏锐度,从我接触的经验来判断,Web 前端同学意识更好一些。

另一方面 Web 界面布局排版方面迄今为止最好的引擎。就表现力来说,CSS 较客户端更为丰富。这么举个例子可能更好理解,熟悉 CSS 的工程师,学 Android 几种布局,理解起来用不了几个小时,反之客户端工程师学 CSS 布局可能就复杂多了。

Web Full-stack(全栈)如何定义?广义上我认为是基于 HTTP 协议基础上的 Web 生态技术栈。狭义上是基于 Web 前端+Node.js 技术栈(虽然我并不认同狭义等同于全栈的定义,但事实上很多 Web 前端已这么认为)。

就 Node.js 来说,现在还远不及 Java 等传统后端语言的生态成熟,所以踩坑是必经之路。例如,很多业务中间件没成熟方案,需要自己开发;运维方面较传统后端尚不成熟,也就前期不会有专职的 Node.js 运维,因此 Web 前端有时还需兼做 SRE;加之语言特性,Node.js 用在复杂业务环境里验证还需时日。

最为推崇全栈的公司非创业公司莫属。这里需要提醒的是,在全栈模式下千万不要忽视培养自己的专业能力,变成了万金油 — 熟称什么都懂,但什么都不专。一旦团队上规模,专业化分工是必然之路,只会使用技术框架的工程师就会丧失竞争力。

那最后再总结一下 Web 端放到大前端里是个什么位置呢。创业公司偏全栈(其实是啥都干,熟称全干开发)模式。专业团队里是两种 T 型模式。这个话题可以再展开,放大一点就是程序员职业生涯的话题了,这次不是重点,可以下次再聊。

五、Web Leader 与 大前端 Leader

Web 端与 iOS/Android 端的转变,首要的问题当然是学习每个端的专业能力,了解 Android 几大组件,OC 语言;一款应用是如何开发的;其实这有个偷懒的技巧,在大公司里去看看相应的技术委员会(有公司也称为技术通道)里每个阶段所需具备的专业能力是什么,去学习和了解一遍。

这里重点聊聊对于哪些能力是可以复用的呢?

首要的一点,我认为 Leader 能对用户体验有敏锐感知的能力与良好的品味。例如对两个不同的 App 同样的实现,能发现和识别,并有自己的观点判断体验好坏。像 App 里都有查看图片,放大图片,切换图片,返回图片列表等操作,同样两个 App 使用后可以判断出优劣。

其次是业务理解与协调能力。发现大前端之间的协作问题,使之互补高效工作。在做 Web 桥与容器时,如何识别多业务中与各端的重点问题,协调各端高效高质地完成这很不容易。Web 端与客户端的全端的性能监控系统,既要多端共同研发,还要能识别多端性能异同点。

当责任权力越大时,要求的是快速理解、识别出关键环节的能力,同时还要协调关键资源,高效高质完成项目。

最后是不断总结优化的系统工程方法。我记得刚开始接手团队时第一件最棘手的事就是如何降低 iOS 的 Crash 率。这个问题用以往在 Web 端的专业技能是丝毫帮不上忙的。但可以从工程角度看,从监控、上报、分析、修复、呈现等环节入手看是否能发现问题;再从统计的角度看 TOP 10 的 Crash 什么是主要因素,针对性地修复,做到问题收敛;再把经验沉淀到测试与持续集成,提前识别和暴露问题。

对于 Leader 来说,最大的问题与阻碍是「经验主义」。经验在一个领域很重要,起到「少走弯路」的作用。但对大前端来说结果本质相同,技术领域不同的场景,有时很难做到放空去理解问题。在此唯有一条经验可以分享,尽可能不装,不推,放低姿态。

六、大前端的春天

不管是 Web 端,iOS,还是 Android,对大前端工程师来说,这是最好的时代。你可以通过这漫天的前端培训看出来,TOP 3 的 IT 培训排名是:1. UI 设计师 2. Web 前端 3. Android 开发。iOS 不在高顺位的原因是大学生没设备(iOS & Macbook Pro),这是最大的门槛。

拿很多公司的业务开发来说(不含基础设施和大数据),放在几年前 1/3 是大前端,2/3 是后端。而现在则是一半以上是大前端的人,已占到一个业务所有研发的 1/3 了。这充分说明大前端的重要性。

同时,大前端的融合越来越强烈,正如我文中开始所说,很多公司和业务已慢慢以大前端的组织结构来划分了。但是高级别的大前端 T 型工程师却很少。

我相信,行业中会出现越来越多的前端 Leader,由此证明前端职业发展的路可以,也会走得越来越远。

Chat实录:《Rank:大前端的前进之路》


enter image description here

enter image description here