tmallfe / tmallfe.github.io

天猫前端
http://tmallfe.github.io
3.93k stars 508 forks source link

让需求来得再猛烈些——快速响应需求的天猫H5首页新架构 #35

Open suprise opened 8 years ago

suprise commented 8 years ago

前言:

作为一名前端工程师,恐怕最经常听到的词就是: 改需求。 作为一名产品,恐怕最头疼的就是: 前端排期已经排到两个月后。 想了解首页新架构是怎样仅仅上线15个工作日就为前端节省约3个工作日的开发时间吗? 请听我细细道来~

从首页的业务说起

天猫首页是天猫的一项业务,而一项业务的技术架构,与这个业务的特点是息息相关的,所以需要先了解首页的业务,才能更好地理解技术架构的演变。从业务上,首页一直承担着以下两个职能:流量的集散地、拉动用户的留存、门面与标杆。

  1. 流量的集散地。首页作为一个流量非常大的页面,是各项子业务流量的重要来源,因此各个业务模块需要频繁地进行调整,对各项子业务进行支撑。
  2. 提高转化率,拉动用户留存。目前首页几乎所有数据都采用了个性化方案、根据人群、地域的因素进行推送
  3. 门面与标杆。对于首页而言,部分用户追求的是『逛』的体验,且首页处于GMV漏斗的最上层,因此首页的体验更为重要。

以上几个特点,对于前端所要面临的挑战就是: 频繁的布局调整多系统对接数据来源更好的性能与稳定性等几个问题。

对接多数据来源 一张图让你感受首页对接多系统的痛苦,还是省略了后续接入其他什么鬼系统的情况下。(不要问我为什么首页没有专门的服务端同学,而是要前端自己对接……)

针对这几个问题,我们则是通过: 动态化布局+ 异步渲染&对接优胜美地(猫客服务端)来解决。同时本文也对首页升级MUI4.0、埋点、性能、容灾与监控等方面也做了介绍。

1. 动态化布局

解决痛点:你们知不知道双十一期间首页紧急发布多少次啊? 简直要哭了出来。 大部分的需求都是各种模块位置调整、频道增减,虽然Web最大的优势在于发版快捷,可也不能这么搞啊……但俺们工程师的一项主要任务就是 (皮) (实) (耐) (操),没办法,只好撸袖子解决这个问题了。

基本原理

众所周知,改配置的成本和风险要比改代码小得多(前提是配置经过测试)。 所以解决办法就是动态化布局, 指的是抽象一套配置文件,根据配置文件渲染页面。当页面有临时需求变更时,只需更改配置,无需开发。 更进一步,抽离配置后,实现可视化功能更加方便,可以将更改配置的任务交给运营,将解放前端的生产力。

具体方案

那么问题来了:怎么抽象是一个较为合理的方案呢?当然是以常见的视觉设计稿为依据。 常见的视觉设计稿基本如下:可以抽象为 业务模块、布局、UI组件三个层次(不将组件拆分为更细的层次,控制复杂度)。 从图中可以很清晰地看见, 布局和UI组件是可以自由地组合的,如模块0是由一排二布局和单图组件组成,模块A是由一排二布局和上图下文组件组成。

通过积累布局和UI组件库,当新增一个不是很复杂的模块甚至页面时,可以 快速地更改配置即可上线~(当然它也不是百分百动态配置,假如后续要新增布局类型和组件,那还是要代码实现的,只是绝大部分可以复用)

动态化布局的大致思想如此,在实现上,每一家都有自己的路数。

解析引擎流程

后端生成配置系统、运营投放系统暂且略过不表,前端 解析引擎大致流程如下:

要注意的点:

1,性能。模板按需加载,模板预编译,优先渲染首屏、图片懒加载支持等等。 2,埋点。包括点击埋点和曝光埋点,具体实现不表。 3,依赖技术选型。例如模板渲染器,因为首页不涉及复杂的逻辑,所以选用的还是较为轻量的xtemplate;还有ES6、模板加载器的选型、工作流的构建等等。 4,文档、脚手架、测试用例等等

2. 异步渲染

一个页面是由数据和模板渲染而成的,同步渲染是指在服务端进行渲染,而异步渲染则是指在浏览器端各自获取数据和模板,再进行拼接渲染的方案。

采用异步渲染主要的优点:

前提:因为手机端的用户习惯较为类似,在视觉设计上,客户端和h5首页也采用了较为一致的方案。部分优点基于此前提。

  1. 可以和客户端首页采用同一个数据源:使运营只需填写一份数据,减轻工作量;
  2. 和客户端共享服务端,对接其他系统时 前端无需开发,且服务端只需开发一份代码。
  3. 接入其他系统时,服务端的并发 请求耗时更短,大约是浏览器端并发请求耗时的10分之1。
  4. 节省成本,原先需要支持h5首页的https接口,外部系统要新建服务器、配置https证书等,简直痛不欲生,现在只需服务端对接就好啦。
  5. 更少的流量消耗,首页的模块较多且类似,异步渲染可以复用模板。
  6. 可以由服务端控制, 更细粒度更精确的ABTest
  7. 更少服务端的渲染消耗。
  8. 后续的其他可扩展性:比如模块间的个性化等

最后h5首页的架构简化为下图,对于前端而言,对比之前的是不是清晰很多?

需要注意的点:

  1. 异步渲染时的接口耗时。 这一步的主要耗时是建立网络连接的耗时,在一些环境里(如手淘),可以复用已有的网络连接,省去建连耗时(需防止lib-mtop版本冲突);还可以将 JS脚本下载与接口调用并行
  2. 低端机器的性能较低,JS执行较慢。 对于这一问题,一方面可以拆分优先渲染首屏,另一方面根据统计,低端机器正在逐渐退出市场,后续将不再有此问题。
  3. 环境问题。 与客户端不同,h5页面可能嵌入其他APP,根据实际的环境不同,可能有些业务上的调整,所以识别环境也是要注意的点。

    3. 率先落地天猫前端基础组件新规范

时代总在进步,MUI规范(天猫前端组件规范)也来到了4.0版本。 MUI4.0 主要有两个特点:

  1. 基于ES6和W3C规范。快速享受 最新鲜的技术优势。
  2. 不再限定某一框架。基于 更细粒度的feLoader、DOM、Fetch等模块完成操作,基于commonJS管理模块,后续调整、兼容其他框架会更加灵活。

首页作为一个轻逻辑但具有一定复杂性的页面和技术标杆,自然率先对MUI4.0规范进行了落地尝试。虽然也踩了一些坑,如所有依赖组件并未都立刻升级到MUI4.0,所以也采用了一些兼容方案。结果也使得首页向极致的性能优化更近一步。

4. 埋点

数据是业务的指南针,因此丰富的埋点信息格外重要。 埋点通常分为点击埋点和曝光埋点,首页改版后,为了更好地支撑业务,针对每一个模块进行了细粒度的曝光埋点,同时针对slider轮播的每一帧进行了曝光埋点。与内部某系统对接,曝光埋点参数的产生、解析逻辑由服务端控制。

5. 其他:性能、容灾、监控

的确做了一些事情,只不过暂时还没有达到最终目标,暂时允许我先卖个关子,后续完成了会再发文分享~

尾声

其实还有很多由其他同学协助完成的内容,如迈入ES6的时代、工作环境的构建等等,但那又是另一个话题了~总而言之,技术架构是根据业务特性、某一段时期和有限资源下决定的,也会不断地演变,所以本文仅供参考~

zhoukekestar commented 8 years ago

1、MUI规范(天猫前端组件规范)目前有开放吗?又向polymer或webcomponents的标准靠近吗?至少我很想这样做。 2、不再限定某一框架,这个我喜欢,我目前也往这方面靠近。赞一个! 最难的还是定一个比较靠谱(主要还是兼容)和靠近标准的标准,包括组件标准和布局标准,能大概说一下在天猫中的这些标准吗?能普遍推行和可以公开的标准。

guirong commented 8 years ago

@zhoukekestar 后面有机会介绍这部分具体的方案及思考

zhoukekestar commented 8 years ago

还有一点,因为页面很多元素都组件化了,组件内的数据如何获取?换言之,就是组件内部的模板的数据如何获取然后进行绑定的?组件是通用的,但不同页面的接口肯定不同,如果要达到很理想的状态的话,还需要对后端的接口数据做组件化层面的拆分,然后在通过不同组件的配置将接口也进行combo。。。这,我怕被后端集体群殴啊~~这,天猫是怎么解决的?谢谢~

icepy commented 8 years ago

期待MUI规范开放,想参考;

2px commented 8 years ago

react-web什么时候开源呢?

SFantasy commented 8 years ago

@2px https://github.com/taobaofed/react-web 这儿

zhoukekestar commented 8 years ago

并不是很喜欢目前很多web框架(不过react-native很不错,给我们前端一条走向app的路),个人觉得当前许多框架和w3c的标准相去甚远,不是很喜欢框架类的(喜欢polymer等比较符合标准的,需要翻墙),希望能用或靠近标准的用法去写代码(使用polyfill等)。所以参照polymer建了个模块来达到类似的功能:https://github.com/zhoukekestar/modules/tree/master/src/webcom 我已经在这个项目中使用了这个模块了,希望大神能给给意见,前期把问题考虑全一点,这样以后才可以轻松点,谢谢~~

Shany100 commented 8 years ago

首屏的内容也是异步加载的吗?

zhoukekestar commented 8 years ago

应该是的,基础库(css&js)+布局+组件+数据,貌似都是异步的

suprise commented 8 years ago

@zhoukekestar 不好意思回复晚了,关于接口combo,的确是有一个后端接口来对接其他所有的系统,不是串行combo,而是并发。为什么采用后端并发:1,因为首页接入的系统太多,不后端来并发请求而是前端来并发的话,整体性能可想而知……;2,接入的其他系统不用再购买https证书……

zhoukekestar commented 8 years ago

@suprise 谢谢您的回答,还是有很多东西要靠自己慢慢探索的, <( ̄ˇ ̄)/

qinyang912 commented 8 years ago

👍

zhanyouwei commented 8 years ago

Hi,该方案中没有提到版本问题,请问是怎么解决的呢

suprise commented 8 years ago

@zhanyouwei 不好意思,没太明白,是什么版本问题?

zhanyouwei commented 8 years ago

@suprise 就是静态资源版本控制如何解决的呢。

renaesop commented 8 years ago

@zhanyouwei 看起来像是通过构建工具插入静态资源的tag号

suprise commented 8 years ago

@zhanyouwei 有一个统一的模块版本配置seed来管理所有版本,渲染html的时候将最新版本的seed引入。这个是目前天猫的模块机制的一部分,可以参考https://zhuanlan.zhihu.com/p/21271376?refer=tmallf2e

xiaolulu commented 8 years ago

大神,帮忙介绍下埋点,我现在处理h5之间(如A-B)的跳转,出现丢失,网上建议使用window.name处理,不过这样需要原业务人员多配置一项该打点是不是跳转命令,这个你这里是什么样的方案呢。 另外打点整体丢失率在多少是在合理范围内的 感谢!

liyahuan commented 7 years ago

这种模式还是试用于这种大型的网站吧,一些国外的网站还是换需求就重新做页面,毕竟前端人太少了。