写点什么

专访阿里资深前端工程师桐木:站在 10 年研发路上,眺望前端未来

  • 2016-06-19
  • 本文字数:6439 字

    阅读完需:约 21 分钟

经历了近 10 年的发展,前端从刀耕火种到百花齐放,繁荣下孕育着一些趋势和变革。站在现在看未来,前端的边界在哪里,如何跨越这边界?如何看前后端分离?如何看全栈?前端工程师的未来是怎样的?

桐木,阿里巴巴 B2B 高级前端专家,专注前端十年。从浏览器到 Web 前端,从数字电视到互联网,从社交到电子商务,从技术架构到团队管理,桐木老师从这些不同角度出发,深入前端领域,积累了很多经验,悟出了很多道理。桐木老师对前端的发展有着自己的看法,InfoQ 带你和桐木老师一起,看前端发展,预测前端未来。

InfoQ:请您介绍一下自己的工作经历,以及目前在阿里的工作职责,包括目前所负责项目和团队。

桐木:我的工作经历大致分三个阶段,从数字电视行业到互联网行业的社交方向,然后又到电商方向。

我刚毕业时,误打误撞进入了数字电视行业,主要工作是做机顶盒上的前端开发(当时的中间件架构,UI 层是基于 Web 的,和后来的 Web OS 有点像)。我在这个行业里摸爬滚打了四年,其中三年是做前端开发,一年是做浏览器开发。

2011 年,Q+ 的一则招聘广告,激发了我对互联网行业的热情。遂加入腾讯,在即通做平台类产品,同时负责团队的基础建设。2014 年下半年,我加入阿里 B2B,进入 B 类电商领域,从此又得到了不一样的氛围和发展空间。

我目前的工作职责主要是技术架构和团队管理两方面。我的团队负责的业务是 1688 这一块的电商中比较基础的平台类业务,比如商品、交易、旺铺、会员、运营等。

InfoQ:您所负责的前端项目架构是怎样的?有没有用到 Hybrid 模式,为什么?

桐木: 1688 的基础业务发展了很多年,在这些年里前端领域的技术也一直在飞速发展,所以前端的架构也一直在演变。WebView 中留下了技术发展的脉络和痕迹。比如在一些古老的业务中,还有早期的 Prototype 式的,以及命名空间来挂不同模块的代码,还有晚一点的 YUI 的代码,然后接下来进入一个主流的“jQuery + amd loader + jQuery components”的时代,这部分代码现存的还比较多。

近几年我们不同团队也尝试了 ng、avalon、react、vue 这些 mv* 的框架,这个方向最终被我们收拢到 PC React、无线 vue & react 的路线上来。总的来说,我们自己造的轮子不多,大体脉络是 YUI→jQuery→mv*,工程体系也是这几个东西的周边配套加上我们的一些定制。

Hybrid 当然有用到了,原因是,想要在动态化、开发效率和用户体验三者之间取得一个平衡,在两三年前也没有多少别的选择。

Hybrid 方案本身是为了在实际的项目中,使得 Native 与 Web 互相取长补短,互为备份的。这里可以特别提一下的是,需要做到面向未来的一些权衡:原则上能用 Web 做的还是尽量 Web 来做,有标准的尽量用标准,遇到碎片化、底层能力不平坦的情况,则采用 Polyfill 的方式。一些为了性能和体验做的一些事情,尽量对 Web 开发者透明,架构设计上正交出来。

InfoQ:您所负责的项目是如何适配不同的设备和端的,有没有高效的方法是非常值得借鉴的?

桐木:刚才的问题中已经提到了一些,那么现在另外提两点。

首先,我们在很多场景下做到了 PC 和无线使用一套核心代码,不同端一套代码。这背后一方面是对前端模型层和后端数据及模型的梳理和抽象,不同的设备和端,在模型层其实差别很小,这部分抽取出来以后就是稳定可公用的一层。另一方面,View 层虽然看起来不一样,但很多东西用语义化的方式去描述,又能再次屏蔽掉一些差异。所以到最后有差别的部分只是 CSS、交互逻辑、数据的适配和定制以及少量 View 定制了。

第二,对于端的碎片化,我们有一部分通过 Native 能力来抹平,另一部分,我们引入了 UC 的 WebView,也极大的帮助我们屏蔽了一些底层差异。

InfoQ:您认为前后端分离的意义大吗?项目中是否做到了真正意义上的分离?

桐木:其实我们这边不太喜欢提前后端分离,更喜欢讲前后端融合。从技术架构来看,需要把数据模型和展现层分离,这就是所谓前后端分离。那融合怎么讲呢?是讲实施层面和人的层面,因为 B 类业务的复杂度、跨越业务复杂度的门槛往往大于跨越技术复杂度,所以,如果我们能把两边的技术门槛,通过服务化的方式降低,那么在写业务的时候,就可以根据情况,通过后端服务化的方式让前端来把 Controller 也给写了,或者反过来,通过前端服务化的方式让后端把 View 给写了。

所谓真正的分离,应该是在架构层面的解耦,也就是说,不管你是前端还是后端,除了一层 Schema 约定之外,写 Controller 的时候完全不要考虑 View,写 View 的时候完全不要考虑 Controller。在这方面我们算是已经摸索出一条路来,近来还有一些有意思的想法和实践,有机会的话会和大家详细分享。

InfoQ:App 混合开发的优缺点有哪些?是否会成为主流?

桐木:混合开发主要是为了实现动态化和节约开发成本,但 WebView 里跑的部分无论如何也很难达到 Native 的性能和体验。目前很多技术的发展其实都是在改造 WebView,试图甩掉一些包袱或者说历史负担。有人可能会奇怪,WebView 有哪些历史负担呢?我们可以来仔细看看:

首先,是标准兼容上的包袱。由于 WebView 作为一个通用的浏览器内核,本身要求具备向前兼容性,比如虽然用 flexbox 布局浏览器可以更高效地 layout,但为了兼容它仍然必须得能认得浮动布局、相对定位布局甚至表格布局。这些逻辑交织在一起非常复杂,牵一发而动全身。假设我现在 fork 一个新的 WebView 出来,裁减掉 flexbox 之外的支持,就大大降低了 layout 逻辑的复杂度,即使不做优化就已经能快不少了,更何况情况变简单以后还能够针对 flexbox 布局做专门的优化,获得更大的性能提升。

其次,浏览器的内部机制以及 js 语言在设计上,其实也有一些历史包袱。比如浏览器从一开始设计,js engine 和 dom engine 就是两块独立的黑盒,js 调用 dom 时相当于一次 rpc 调用,每次调用都会涉及上下文的保存和恢复。同时,js excute 和 dom render 是跑在一个线程里的,即使两者没有调用关系,dom 也必须等 js 执行完毕才能 render。这两件事的结果就是网页在运行过程中会在这两个黑盒之间来回切换,各种上下文切换,各种互相等待,这样一来掉帧就在所难免了。所以,如果我们能够让 js engine 和 dom engine 在执行层面能够打通,变 rpc 调用为本地调用,就能加快不少。更进一步来说,如果能够有效利用多核,把 js excute 和 render 在一定条件下并行起来,或者把 style resolving 和 layout 并行起来,也能提升新性能。

再次,WebView 本身确实也在越变越快,但有些 OS 的限制或者一些设备老旧 WebView 的存在,会导致碎片问题,这也在拖慢我们的脚步。这个大家比较熟悉了,例如 iOS 的 Nitro、WKWebView 之于 UIWebView,还有 Andorid4.4 之后的 Chromium WebView 之于之前的 WebKit WebView。

老郭的 BeeFramework/Samurai、阿里的 birdnest,是在甩前两项包袱,一方面取 Web 标准的子集,一方面把所有东西都拉到 Native 的 runtime 里执行;FB 的 React Native 和阿里的 Weex,主要在甩第一项包袱(部分优化了第二项);Mozilla 的 Servo 致力于并行化和 GC,主要是在甩第二项包袱;Intel 的 crosswalk、微信的 X5、阿里的 UCWebView 等,是在一定范围内甩第三项包袱……大家为了甩掉这些包袱,都提出了不同的解决方案。

不论大家走哪条路,有一个共识还是大家都找到了的,那就是看齐 Web 的几个标准。因为 Web 的技术体系在 UI 的描述能力以及灵活度上确实设计得很优秀的,而且相关的开发人员也好招。所以,如果说混合开发指的是 Native 里运行一个 Web 标准,来看齐 Runtime 来写 GUI,并桥接一部分 Native 能力给这个 Runtime 来调用的话,那么它应该是一个永恒的潮流。

InfoQ:全栈的具体含义是什么?阿里是否鼓励工程师朝着全栈工程师的方向去努力?

桐木:全栈这个词挺时髦的,含义么,不就是啥都干,万金油么。

其实很久以前,哪分什么前后端,大家都是工程师,从头到尾,从数据库设计到接口实现,再到前端展现,从存储过程到负载均衡再到部署运维,大家样样都得搞。

但行业在发展,每个细分领域都越来越复杂,要从头搞到尾既不是不行,也不是太辛苦,而是根本就不可能。真要都搞的话,那么对每个领域的了解只能是半瓶水,搞出来的东西就是玩具。那怎么办呢?这就需要专业细分,在分工以后各自往深处去发展。

但问题又来了,分工以后我们还是需要把各环节连起来,这对接口设计提出了要求,还要考虑去联调这个环节。分工以后有了上下游关系,工期大家也需要配合好。

另外,还有一个情况:假设有两个业务,业务逻辑非常复杂,我们有两个人来做。如果是一个前端一个后端,那两个复杂业务的大部分细节,都是两个人都要了解的。因为 B 类业务特别复杂,所以这种情况比较普遍。这时候又不能直接退回到原来的“万金油”模式上去,怎么办呢?

全栈的模式这时候就被提出来了。全栈和最早的万金油模式的不同之处在于,每个领域通过服务化的方式隐藏了大量复杂度和细节,全栈工程师主要关注业务逻辑和业务架构,以及为了实现业务架构,必须掌握的前后端在服务化边界上的技术以及解决方案。这样就可以以比较小成本,由两个人分别把两块复杂业务扛下来了。

对于是否鼓励全栈的问题,其实,只要是有利于提升整体生产率的方式肯定都是鼓励的。全栈是否能够提升生产效率呢?这和业务特点、前后端的服务化水平,以及团队的人员结构都有关系。另外,也需要考虑个人意愿。所以,我们从两方面在推行这件事。一方面是在识别出来全栈确实能够提升生产率的场景下,通过提升服务化水平,来让这件事可能发生,这是外因;另一方面,通过职业发展路线、晋升标准和 Job Model 等配套设施的优化,配合技术新鲜感成就感的培养,甚至大量福利,来促进一批偏业务的、有全栈意愿的同学能放心且踏实地在这个方向发展下去,这是内因。

目前阿里推进全栈的 BU 不少,大家的阶段不同,取得的进展也不同,至于最后的结果,让我们拭目以待。

InfoQ:在前端领域中,如何立足当下,面向未来呢?

桐木:这个话题是我感受相当深的,不光是技术上,在职业发展、技术管理、架构治理过程中,我发现过去的很多经历都和这句话有或多或少的关系。

提一个早点的例子,在做嵌入式的浏览器的时候,WebKit 还没火起来。那时,我们维护着一个内部自研的浏览器引擎,当时 js 引擎和 layout 都有各种 bug,而且从设计上非常难解决。到 2009 年底,Android 1.5 上 WebKit 的时候,我们意识到该放弃手上这个 Web core,然后切换到 WebKit 了。这是一个较大的转折,当然,中间件全面转 Andorid,也是不可逆的潮流。而这件事,则表明了视野和对未来方向的把握很重要。

面向未来,体现在职业发展上,从广电行业来到互联网,以及在周围前端大批转 iOS/Android 时坚守前端,这里面没有什么对错,但背后也是对趋势的判断、对未来的一种相信。

面向未来,也体现在技术架构选择上。比如:无论是鸟巢还是 Samurai,早期的 DSL 设计都是 Web 标准体系比较远的,后面都不约而同的切换到了 HTML+CSS+JavaScript 这套标准上来了。这里体现了一个原则,就是能用 Web 做的还是尽量 Web 来做,有标准的尽量用标准,遇到碎片化、底层能力不平坦的情况,则采用 polyfill 的方式。

面向未来,还体现在接口设计上。不过这里要举的是个反例。

例如现在经常说的一个反模式:“除非你是在很明确的知道自己在做 polyfill,否则不要去扩展原生对象”。这样做有什么坏处呢?有人可能脱口而出:“扩展了 prototype,会破坏 for…in 时对象的纯净性”。恩,这是个原因,不过因为之前的这种遗毒,大家现在都很习惯 for…in 的时候用 hasOwnProperty 过滤一下了。

但最大的原因还不在于此,而在于这样做“失去了对未来扩展的兼容”。怎么理解呢?我这里举个具体的例子大家可能就明白了:以Array.forEach方法为例,在比较早的年代,Array 对象下面并没有这个方法,当年 Prototype 库的引领下,很流行用扩展原生对象的方式来“方便"地增加一些好用的特性,于是很多人都用添加原型的方式自己添加了一些方法给 Array,其中就有不少人添加遍历方法时正好选择了forEach这个方法名,就像这样Array.prototype.forEach=fuction(){...}

这样看起来好像挺不错的,但问题在哪儿呢?我们一起思考:

你当时怎么知道以后规范不会往 Array 上加 forEach 这个方法呢?
好,我确实不知道,所以保险起见,我防御性地加个if(!Array.prototype.forEach)的判断总行了吧?

问题是你怎么知道以后标准的这个 forEach 内部实现是不是跟你一模一样?
好,你运气比较好,里面的内部实现还真是一模一样的。

问题是你怎么在规范出来前知道这个 function 的参数是几个,什么顺序?
说实话,这个在设计上是很难预测的,比如 jQuery 的 $.each 方法,三个参数的顺序就是index,value,array,而后来规范中的 forEach 三个参数顺序是value,index,array。所以设想下,如果你当时用上面的参数顺序扩展了 Array.forEach,那么在标准出来之后,请问你准备怎么修改,才能够让全站所有依赖这个方法的代码和去和新的基于标准方法的代码来愉快地玩耍呢?

面向未来之外,更需要立足当下。

我身边有一些架构治理、技术管理的例子,但因为需要交代太多背景,不方便展开,我觉得可以举 HTML5 和 XHTML2 标准之争的例子。

HTML5 为什么能够打败 XHTML2 成为事实上的标准?有人认为浏览器开发商更有事实上的话语权一些,所以打赢了。但我要说这里面更多的是 HTML5 遵循的理念带来了胜利。我们来看看它背后的几个理念:

  • 避免不必要的复杂性:关键是既能避免不必要的复杂性,还不会妨碍在现有浏览器中使用
  • 向前兼容,平稳退化:老的写法哪怕设计有缺陷,也得保证运行时不被破坏,但开发态我们可以用工具来引导大家规避掉有缺陷的写法;一些新的特性,在支持的情况下给用户更好的体验,在不支持的情况下,也能保证基本的体验
  • 务实、接地气:努力吸取并改进民间的解决方案,不执着于追求理论上的完美。
  • 最终用户优先:一旦遇到冲突,最终用户优先,其次是作者,其次是实现者,其次标准制定者,最后才是理论上的完满。

这些理念保证了一个标准能够在推进过程中,能够不对现有生态产生破坏性颠覆性的影响,能够争取尽可能多的人的支持,可以通过渐进的方式,由点及面的方式来落地。

当然,渐进性改革有时候却可能缺少点魄力,什么事情都不是绝对的,不是还有休克性疗法么。这里说的是针对一个复杂系统的一种解决问题的思考方式和策略,大家根据目标、场景、适用人群需要有不同的选择。

InfoQ:您专注前端十年,在您看来前端的发展是否会带来突破性的变革?

桐木:其实前端的发展在这两年已经有了不小的突破了,之前是一些边界上的扩张(服务端、移动端),然后是工程化及生态的完善(模块化、包管理),近期是语言、标准本身的一些进化。

归根结底,前端的发展与设备及交互方式的变革是分不开的。十年前我们访问的网页,和我们现在访问网页,在设备及交互方式上的变化是颠覆性的吗?并不是,我们的设备也就是从 PC 到了手机,在屏幕大小和交互方式上发生了一些变化,相应的,它们各自的机器性能、Runtime 性能也有一些提升。但这些变化都算不上革命性的。

那么接下来十年呢?设备和交互方式会有变革吗?

可能大家已经看到了,VR 和 AR 最近很火。在看得到的未来,我相信变革会因 VR 和 AR 的发展而发生,届时前端的很大一部分技能树,可能会完全发生改变,相应的标准也会往前迈进一大步,甚至前端的边界也可能会发生很大的变化。到那时候,称前端工程师为“视觉与交互工程师”或许更为贴切。

不过话说回来,我比较保守,我认为“视觉与交互工程师”这个工种出现的时间不会太近,最近看到的一些 VR 和 AR 产品,我觉得成熟度还不够。基于原生 API 开发的应用都捉襟见肘,更不用说在此之上产生生态和诞生相应标准,并形成类似浏览器这样的 UI 及交互的统一平台了。前端工程师要成为 VR 时代的”视觉与交互工程师”恐怕还得等一阵子。


感谢郭蕾对本文的审校。

给InfoQ 中文站投稿或者参与内容翻译工作,请邮件至 editors@cn.infoq.com 。也欢迎大家通过新浪微博( @InfoQ @丁晓昀),微信(微信号: InfoQChina )关注我们。

2016-06-19 19:007466
用户头像

发布了 28 篇内容, 共 17.4 次阅读, 收获喜欢 29 次。

关注

评论

发布
暂无评论
发现更多内容

一个用于学习KVM的迷你虚拟机

ScratchLab

虚拟机 虚拟化 kvm VT-x

腾讯一面:说一说 MySQL 中索引的底层原理

老周聊架构

MySQL 3月月更

bigdata作业2

Pyel

自己动手写Docker系列 -- 5.1实现容器的后台运行

Docker

40行不到的Python代码实现超燃动态排序图,成为一名合格Python架构师

程序媛可鸥

Python 程序员 面试

架构师实战营王者荣耀商城异地多活架构设计

刘洋

#架构实战营 「架构实战营」

架构实战营毕业总结

novoer

「架构实战营」

LabVIEW实现CRC校验

不脱发的程序猿

LabVIEW CRC校验

Ubuntu18.04下QT开发Android无法连接设备问题解决

DS小龙哥

3月月更

掌握《网络》,见微才能知著

蔡农曰

TCP https 网络 HTTP TCP/IP

2万字详解测试金字塔

俞凡

最佳实践 测试 研发效能

ICT的圣杯(三):产业融合的技术乐章

脑极体

手把手教你用 Vue 搭建带预览的「上传图片」管理后台

蒋川

Vue vue admin

2022 年顶级机器学习算法和 Python 库,【原理+实战+视频+源码】

程序媛可鸥

Python 程序员 面试

云上业务配置选型的一些小Tips

穿过生命散发芬芳

3月月更

模块九:毕业设计

黄秀明

「架构实战营」

【面试-经验之谈】面霸是如何养成的,他的路子真的野

测试猿温大大

面试 涨薪 测试工程师

高并发架构实战课 期中测试:某达架构设计说明书

👽

李智慧 高并发架构实战课 李智慧

工作想法小计(5):3/7 - 3/18

非晓为骁

个人成长 细节 工作想法

聊一聊C语言位域/位段

不脱发的程序猿

C语言 嵌入式开发 位域/位段

尤达 DDD 领域驱动设计思想 第四章作业(使用事件风暴建模法对SmartRM系统的交易域重新建模)

代廉洁

尤达DDD领域驱动设计思想

4 行代码实现批量、快速安装 Python 第三方库,价值2000元的学习资源泄露

程序媛可鸥

Python 程序员 面试

面试突击32:为什么创建线程池一定要用ThreadPoolExecutor?

王磊

java面试

10 行 Python 代码自动清理电脑内重复文件,解放双手!

程序媛可鸥

Python 程序员 面试

模块九秒杀作业

novoer

「架构实战营」

一个LabVIEW控件,生成模拟波形效果

不脱发的程序猿

数据可视化 LabVIEW 生成模拟波形效果

《不敢止步》--读书笔记

stars

从简单代码入手,分析线程池原理

架构 线程池 池化思想

小程序电商业务微服务架构及微服务框架模式

「架构实战营」

在 Node.js 中使用 Yaml 编写API文档

devpoint

node.js API yaml swagger 3月月更

用 Go 语言打造一个全新的 kv 存储引擎

roseduan

Go KV存储引擎

专访阿里资深前端工程师桐木:站在10年研发路上,眺望前端未来_语言 & 开发_韩婷_InfoQ精选文章