本博客同步自我的GitHub博客
一直想去阿里看看,这次成行,至少 BAT 三总部签到成就是 get 了。经历了多日的降温降水,初到杭州,就赶上了升温,即使穿短袖在阳光下走走也会微微流汗。一大早出门前往阿里西溪园区,担心坐公交来不及,就打车过去,在车上就感叹——阿里的位置真是偏啊,离城区太远了,杭州的地铁只有一条线,像我这种在南京工作,每天地铁穿城而过去上班的方案放在杭州肯定是行不通了。不过因为远离城区,地广人稀,阿里园区也是足够大,不过好在园区内有很多公用自行车可以随便骑,反而十分方便。
园区的环境也是不错的,有很多植物,一些植物上还挂上了介绍的牌子,就像植物园一样。建筑的装饰风格也比较活泼,墙上有壁画,融合了阿里各产品的元素在里面,类似淘公仔和天猫吉祥物的大玩偶也随处可见,看了能让人会心一笑,这点比起我厂过于商务的生硬风格更让我喜欢一点,也有互联网风格。
好了,免费广告不能打太多,下面进入正题。这次是我第一次参加 D2 这个活动,之前有听说过,不过因为还在上学,没有足够的盘缠,也就没能参加。所以这第一次参加在国内可以算得上是影响力数一数二的前端论坛,也是挺兴奋的。到了论坛现场,发现到的还算比较早,主会场人还很少,分会场几乎还没有人到。值得一提的是,在签到的人群中,我看到了张鑫旭大神,他的博客我看过不少,大活人还是第一次见,瘦瘦高高的,皮肤有点黑。
同部门的小伙伴们当天上午才从南京出发,而我是头天晚上就到的急先锋,因此我到的时候大部队还在路上,所以我干脆就单独行动了。第一场的分享在两个会场分别是来自百度 FEX 的前端工程师的《指尖上的数据》和支付宝苏千的《支付宝前后端分离的思考与实践》。苏宁易购在不久之前刚刚有一次 node.js 的实践,算是对前后端分离的一次探索,支付宝在这方面算是走在前面的公司,所以我毫不犹豫的选择了这场分享。圆心的开场讲话一结束,我就冲出门直奔分会场。同时我也发现,很多朋友们的选择也和我一样啊,幸亏我的动作快,居然还抢到了一个前排的座位,要是慢上五秒,就连地板都没得坐了。(同样值得一提的是,玉伯后来就坐在我的前面一排啊,终于得以一睹大神风采~)。
Node.js部分
支付宝前后端分离的思考与实践》苏千(袁锋)
苏千的广东口音听起来挺喜感,人也是圆圆的挺可爱,不过我可管不上这些,忙着边听边记笔记呢。苏千说到,前后端分离在实现之前,主要由以下两个痛点:
- 设计离技术比较远,产品交互体验不佳
- 前后端职责不清晰,研发体验不好
这两点中,第一点相对的偏向用户一些,从用户层面对交互设计是否合理会体验更加直观。而第二点,就是对我们开发者说的。的确,传统的前端制作静态页面,再由后端套模板,然后前后端联调,改bug,测试,上线,再回测。。。这样的流程延续了很久,也被诟病了很久,在这种流程下,前后端的工作有了很大的耦合,不利于提高研发的效率,改善研发体验。
Node.js 在前后端分离中扮演的角色应该是一个中间层,在这方面,除了支付宝外,淘宝的中途岛项目有不同的侧重点。中途岛项目中,Node.js 层在职责上依然属于前端,并没有抢后端的饭碗,而是将一般前后端职责划分模糊的地方进行了分割,后端不再插手前端 UI 层的工作,不在模板上插入各种复杂的逻辑,只负责提供数据,提供服务化的数据接口。Node.js 层要做的就是路由共享,对请求进行分发,当然,路由的工作还可以再加一层 nginx,这点在腾讯的实践中有所体现,这个后文会说。Node.js 层的另一职责便是模板的共享,根据不同的业务场景,选择模板渲染是在服务端完成还是浏览器端完成。例如淘宝的首页渲染是服务端完成,而一些详情页或其他模块就是交由浏览器端渲染了。
说完淘宝,还是说回支付宝。苏千的整个分享过程中,有 70% 的时间都是在说他们的 Chair 应用。它是支付宝前后端分离中的关键环节,它的主要特点是对逻辑的复用,对阿里内部系统的融合,以及统一的安全策略。不过这个系统跟支付宝的很多核心业务相关,因此没有开源,更多的细节也就无从知晓。从苏千所说的话来看,Chair 可以说就是一个完整的 web app。它有路由,有各种中间件,有 C 和 V 之间的协作,以及对支付宝各个服务接口调用的统一管理。可以说,有了 Chair 的服务,前端同学的开发可以想象,应该会很爽。
不过我个人对 web 服务的研究还很浅,苏千的分享在各方面也是蜻蜓点水,更深的理解也没有了,总结成一点,就是后端一定要服务化,很多的数据接口要进行改造或是管理。联想到苏宁几个月前的门店频道项目,其实前台和 Node.js 部分的实现已经没有什么大问题的,就是因为后端的服务不能统一,导致最后没有完全成功,有些遗憾。
在最后的 QA 中,苏千针对一些问题的回答也有些有价值的地方:
- 支付宝前端团队的分工,力求成为多面手,各种工作都要做,甚至能够接手一部分的后端工作。
- 对于一些包含了很多原子接口的大接口,并发请求,这方面由前端来完成
- 后端提供的接口,主要为 RPC,少量 RESTful(支付宝)
- UI 测试在实际浏览器中跑
- controller 控制所有的数据逻辑,并提供给 view 层,视图层只负责渲染。
- 支付宝的前后端分离之路也很曲折,最初是由玉伯在两年多以前发起,也经历了一些失败。听到这我倒是有些安慰,技术之强如阿里,在这方面也是经历了很多困难,我们经历的一些失败也算不上什么,要相信未来是美好的。
《nodejs一小步 前端开发一大步》林楠
下午的第一场分享也是跟 Node.js 有关,是由来自腾讯云的 BrianLin(林楠)带来的 Node.js 在腾讯云的实践。从他的整个分享内容来看,腾讯云对于 Node 的应用更偏后一点,不仅仅是担任中间层的工作,更多的会接管一些后台的逻辑,比如原来由 php 完成的工作。通过一系列对 php 和 Node.js 性能的比较,最终得出的结论是在腾讯云的业务场景下,Node.js 的综合性能会更高一些。
Node.js 和 php 的性能比较,各种论据我就不罗列了,林楠说的没有什么特别让人意外的地方,上网搜搜也能找得到。比较有价值的应该是在应用过程中,使用 Node 会遇到的一些问题以及解决办法。首先是 Node 和 nginx 的协作,在实际的应用中,Node 一般都会和 nginx 搭配,由 nginx 发挥特长,进行一些请求的分发,尤其是静态资源的请求分发。腾讯有自己改造过而成的 tnginx,它的主要工作就是动静态资源的分离,静态页面由 tnginx 直接处理,动态页面由 Node 处理。nginx 的职责主要有三点:
- 域名收归,由 nginx 进行路由分发。
- 灰度发布,应该是类似于 A/B test,由 nginx 进行代理。
- 配置化支持 https 的能力。通过 nginx 配置项实现 https 的支持相对用 Node 来实现要方便得多,客户端和 nginx 的连接使用 https 协议,nginx 和后端各服务之间的通信依然使用 http 协议。
另外林楠还提到了数据存储方面的一些问题,我没太听懂,就不多说了。他还提到一个问题,就是发布时的性能抖动问题,在每次发布过后,性能总会有一段下降的过程,这主要是由于在发布过程中,服务需要重启,在每次重启时,服务请求队列中会有一部分请求没有处理,在新的服务启动时,这部分未处理的请求会对整个服务的性能造成影响,不过具体是怎么造成影响的呢,我不太清楚。就这个问题,我和身边的来自孢子社区的小伙伴交流了一下,孢子社区使用的是 fib.js,它使用了协程,它是一种多现场单线程,每个协程自行建立堆栈,共用一个线程。封装后的 v8 不会感知到协程的存在。完全非阻塞,由纤程驱动,没有 Node 特有的回调模式。JavaScript 线程内会运行多个纤程,在发布方面,每次发布会启动新的纤程,不会影响到原来连接状态中的各种请求,新的请求全部切到新的纤程上,旧的纤程上的连接只要不断开,还是请求旧的服务,一旦所有连接断开,则自动回收旧纤程,达到无缝切换。更多关于 fib.js 的介绍,可以看它的作者孢子响马的分享pdf。这种发布方式在技术上很是新颖,不过可能还只适合孢子这样类型的团队,对于苏宁的实践,暂时只能提供一定的参考价值吧。
前端工程化架构部分
《面向多端的蘑菇街前端技术架构》贝勒(李振强)
我跳过了中间周杰的《第三方开发前端实践》这部分。原因是他的分享我感觉实在是不知所云啊,也不知道是不是我的水平太差,完全听不进去,倒觉得他是在推广自己公司的各项产品。没有参考价值,那么略过不表。
本来,看贝勒分享的标题,感觉他会讲一些多终端适配甚至是 hybrid 开发方面的东西,实际上不是,主要内容也就是蘑菇街一路以前的前端技术架构的演变。倒是和后面京东的分享很相似,正好我此行的目的就是为了听前后端分离和前端架构方面的东西,正合我意,因此我也就把这个分享划分到前端工程化的主题之下了。
蘑菇街作为一个当初的创业公司,在初期技术方案也的确是十分原始的,整个前端部分一句话总结就是 jQuery + base.js。jQuery 是 JS 库,base.js 是对业务开发中常用方法的封装,这样的技术选型根本谈不上什么架构的思想。随着蘑菇街业务的不断扩大,复杂性的增加,过去简单的套用 jQuery 的方案已经不合适了,因此他们开始探索自己的前端工程化架构方式。
目前,蘑菇街采用的前端技术架构为:webdemo作为本地开发环境的名称(这个名字起的很奇怪啊),其中包含两个方面,一个叫 walkman,是前端自动化工具,另一个叫 magpie,作为前端的底层,相当于是将之前的 base.js 进行了升级。
webdemo 这个东西,主要是用来解决一个代码的管理问题。过去蘑菇街的代码是托管在 svn 上,svn 有什么弊端已经不用多说了,庞大的代码量给代码管理带来了很大的困难。还记得在人人网实习的时候,代码库包括静态文件都是用 svn 管理,checkout 一次好像有 5G 的数据量,一旦本地维护出点问题,代码冲突什么的,svn 用的不熟练的人就会苦不堪言,我就是受害者之一。webdemo 这个东西实际上就是一套解决方案,针对代码管理的问题,对后端服务的调用,采用了 nginx + php 的方式,代码托管平台也迁移到了git上,并且提出一种子模块(submodule)的概念,将pc端、h5、pad 和 im 的代码分别管理,我想应该是用 git 切了不同的分支。在开发环境上,使用 require.js
进行模块化开发,预编译 css 采用 less,对 less 的处理用了 php 的 lessc 模块在服务器端进行编译,同时使用 sourcemap 对源文件进行引用,便于开发调试。
前端底层名为 magpie,它的一大作用是统一了各终端的开发方式,提供了一些全局变量,具体是什么我忘了,就记得名字是 MoGu,我想应该是提供了一些全局的配置信息,比如多种端适配要用的一些东西,或者是一些公用的方法吧。开发模式上,采用了一种类 backbone 的方式,将页面单页应用化,以便于模块化开发,减少各模块的耦合度,提高开发效率,这种方式在中型公司中似乎比较常见。base.js 这个库有什么变化我记不清了,不过由于它是针对蘑菇街的业务高度定制化的,所以参考价值应该不大。
值得一提的是蘑菇街的前端自动化系统 walkman,包括后面京东的 jdf,和我们的 fas 都有高度的相似性,有很大的参考价值。在流程构建方面,walkman 采用了 grunt,在发布阶段,用 r.js 进行打包,开发阶段的模块化异步加载没有必要带到生产上去,因此,自动解析依赖,打包 js 也是不错的方式。孢子的小伙伴给我看了他自己实现的一套打包脚本,不过由于是基于孢子的开发框架,不能直接移植,而且实现上好像还有些不完善。对于 css 的打包,采用 lessc 来完成。我觉得这部分功能其实完全可以集成,不过这还牵扯到一个统一团队开发方式的问题,京东用的 scss 也是一样的。项目脚手架采用 yeoman 来生成,配置方式当然根据蘑菇街的业务形态进行了定制,这点在fas中也有体现,虽然还比较初步。
在数据模拟方面,蘑菇街用的是 lotus,在介绍 lotus 的时候,贝勒还提到了一个叫 mean.io 的东西,据我在 github 上的搜索结果,他指的可能是 mean.js 这个东西,前后端开发先定好开发所需接口和数据格式,达成一致以后前端便脱离后端,完全使用 lotus 进行数据模拟在本地开发,lotus 还可以根据数据接口直接生成文档,便于后期维护和二次开发使用。
对于我比较关心的 hybrid 的内容,贝勒只提到了一个 jsbride,说是一个 hybrid 的开发环境,不过看来蘑菇街的 hybrid 之路也才刚刚开始,还没有什么可以分享的东西,贝勒也没有再多说。
《京东前端工业化实践之路》刘威
这个算是 D2 的所有分享中我最关注的分享之一了,另一个是淘宝的前端工程与自动化体系,无奈两个分享同时开始,分身乏术,考虑到京东的现状相对于淘宝应该跟苏宁更相似,我便选择了这场分享。
来自京东的是一位前端架构师,之前曾就职于百度和新浪。他就京东目前的前端工业化进行了一些分享。总结起来,我觉得京东的前端现状实际上跟苏宁还是很相似的。
京东的前端工具集名为 jdf,在 npm 上提供了模块的下载,github上的仓库可以点击这里,这个工具提供了多种命令行指令,能够完成一系列前端开发过程中可能需要的各种构建工作。京东的开发对模块进行了划分,每个模块可以独立维护,模块有符合规范的目录结构,引用方式类似于{%widget name=""}
,模块的配置文件符合 common 规范。js 的模块化方面采用了同样兼容 commonjs 规范的 seajs 进行模块的加载管理。预编译 CSS 选择了 SCSS,每个文件的命名方式以模块名开头,避免冲突。后端模板用了 velocity 语法,做到了前后端公用。jdf 提供了模块的新建,安装,发布和预览等一系列指令,便于单个模块的调试。内部有模块云平台对模块进行管理,使用 FTP 控制权限,有权限的人可以进行模块的发布,任何人都可以下载模块,模块的版本识别依赖 json 配置项中的 version。
模块方面大致是以上这些。在静态资源输出方面,通过发布至 cdn 然后在资源路径前加 cdn 前缀的方式进行非覆盖式发布,以版本号进行区分。js 资源方面的输出我有点记不清,他好像提到了一个 cmd 模块自动提取文件 id 和 dependencies 的机制。在字符编码方面,由工具进行统一化。性能优化方面,jdf 工具集成了 js, css 和 png 的压缩,js/css 和 css/sprite 的合并,以及 combo 请求的功能。其中对 sprite 的压缩怎么实现我还想象不出来,好在 jdf 代码开源,可以研究一下。
联调的实现主要是静态资源上传至联调服务器,html 上传至另一个联调/预览服务器,没什么特别的。上线过程也比较常规,编译系统去静态资源 svn 上取代码进行编译(他所说的编译应该是至 SCSS 预处理,js 压缩合并这方面的意思),然后发布至cdn。
辅助功能简单罗列一下:
- 本地 serve
- 错误提示
- 自动刷新
- 自动监听
- 代码质量检查:
jslint
,csslint
,htmllint
- 根据配置文件,统一编译,输出
一点想法
总结起来就是以上这些。回顾整个 D2 我所听到的分享内容,结合我对苏宁网购业务的一些了解,我觉得目前最有价值去发展的就是 fas 这套系统,fas 如果有竞品的话,就是京东的 jdf,如果我们有足够的时间和人力投入的话,超越京东不是不可能的事情。对于前后端分离的实践,我还需要多学习,多了解一些相关的知识,怎么去实现这个东西,苏宁有在这方面有实际经验的开发者,要向他们学习一下。
D2 上听到了也只是其他公司相关技术的冰山一角,只有有了雄厚的技术积累才可以从容的进行技术分享,对于我们来说,先做好第一步吧。