miketwais

work up

实现真正意义上的前后端分离------由淘宝引入nodejs引发的思考

说起前后端分离,大家包括我自己都会想到:

当今流行的MVC不就是最标准的前后端分离吗?

说到这里,我不禁要反问,MVC真正的实现了前后端分离了吗?

无论是PHP的MVC框架TP还是JAVA的MVC框架SpringMVC,他们实现的前后端分离或许应该被叫做:一定程度上的逻辑和展示的分离

当然我们不能泯灭MVC带来的贡献,MVC的出现让写代码不再是一行写到底,他给我们带来了分层的概念,并在一定的程度上减少了三层间的纠缠。

但是,我们回忆一下当我们基于MVC写代码的时候,是不是有这样的情况:

这样的一个新闻列表(html+php)

<div class="news">

<?php

foreach($results as $item){

?>

<li class='news_item'><a href="<?php echo $item['url'];?>"><?php echo $item['title'];?></a></li>

<?php

}

?>

</div>

或则是:这样的一个分页(jsp)

<table>

<tr><th>名字</th><th>说明</th><th>图片预览</th></tr>

<c:forEach items="${data}" var="item">

<tr><td>${item.advertName}</td><td>${item.notes}</td><td><img src="${item.defPath}"/></td></tr>

</c:forEach>

</table>

<ul>

<li><a href='?nowPage=${nowPage-1}'>上一页</a></li>

<c:forEach varStatus="i" begin="1" end="${sumPage}"> <c:choose> <c:when test="${nowPage==i.count}">

<li class='disabled'>${i.count}</li>

</c:when>

<c:otherwise>

<li class='active'><a href='?nowPage=${i.count}'>${i.count}</a></li>

</c:otherwise>

</c:choose>

</c:forEach>

<li><a href='?nowPage=${nowPage+1}'>下一页</a></li>

</ul>

在这些个项目中我们的开发人员就是在view层不断的“挖坑”和不断的“填坑”,而且虽然我们用到MVC框架,但是我们并没有真正的实现前后端分离。

如何实现前台人员就写前台,后台人员只管后台,这是我一直在思考的问题。

无论是为了满足业务上的需求:比如,前端变化频繁,或者前端效果要求非常高/跨设备的兼容性要求很高的情况下

还是为了使技术团队更加精进所在领域,团队分工更加明确,能和需求更好对接(界面问题归前台,业务功能开发归后台)的角度来看,我觉得做好前后端分离,是团队建设的很重要的一部。

当然这也是在公司有一定经济基础的条件下,我也是一个实用主义者,提倡为了业务而技术,而不是为了技术而技术。

 

------------------------说了这么多,大多都是我个人开发中遇到的一些情况和问题,下面开始正题了----------------------

 

听闻淘宝引入Nodejs来实现了淘宝团队的前后端分离,下面就看看常见的做法和淘宝的做法,供大家思考

web架构的发展经历了(也可以说正在经历)从后端为主MVC应用时代---->基于Ajax的SAP应用时代---->以前端为主的MV*时代---->基于Nodejs的全栈时代

这个过程也是随着经济发展,人们对审美,性能要求不断提升而发展来的。

在各个时代前后端配合的方式也不一样,分别看一下:

后端为主MVC应用时代

  在MVC架构中一般是前端人员写模板,给后台人员套用,这就是上面说的那种情况,前后台纠缠不清,到最后就是大家一起写了,前台后台一起大包干,根本没有分工了。

 

基于Ajax的SAP应用时代

  随着2004年gmail的诞生,随后也诞生了Ajax,它的到来让SPA疯狂了一把,这个时代前后台分工还算是很明晰的,后台提供接口,前台来调用。  

  同时也带来了一大堆的问题,前端代码过于复杂,而且前台严重依赖后端接口,如果后端数据模型不稳定经常变化,那么前台开发人员就会很痛苦,所谓牵一发动全身。可维护性很差,而且代码难修改。

 

以前端为主的MV*时代

  前几年出现了各种前端框架,有mvc的Backone,有MVVM的angularjs等。。。

  这些框架总的原则是先按类型分层,比如 Templates、Controllers、Models,然后再在层内做切分,

  这个时代的应用实现了前后端分离,前端工作在浏览器端,后端工作在服务端。清晰的分工,可以让开发并行,测试数据的模拟不难,前端可以本地开发。后端则可以专注于业务逻辑的处理,输出 RESTful 等接口。

  但是,这种应用全是异步请求,对SEO不利,前后台都要写逻辑控制,而且无法复用前后台的代码,存在一定程度上的重复开发。URL的设计要严重依赖配合后端,无法自主决定。

 

基于Nodejs的全栈时代

  随着 Node.js 的兴起,JavaScript 开始有能力运行在服务端。这也带来了全新的架构:

 

  这种架构下,存在两个UI Layer层,即他们都负责前台的工作:

    基于浏览器的UI layer处理浏览器层面的展示逻辑,通过CSS控制样式,js添加交互功能,HTML 的生成也可以放在这层。

    基于Nodejs的UI layer处理路由,模板,获取数据,cookie等。通过路由,前端终于可以自主把控 URL Design,这样无论是单页面应用还是多页面应用,前端都可以自由调控。

    这样一来,后端终于可以摆脱对展现的强关注,转而可以专心于业务逻辑层的开发。此时,web server上也是javascript代码,所以一定程度上“前后台”可以复用了,对于需要SEO的场景我们可以在服务端上进行渲染。

    这样基本解决了MV*时代的一些弊病。

 

-------------------------------讲了这么多,我们看看淘宝到底是怎么利用Nodejs实现前后端分离的----------------------------

 

借一张网友的图:

 

看看网友的分析:

  1. 最上端是服务端,就是我们常说的后端。后端对于我们来说,就是一个接口的集合,服务端提供各种各样的接口供我们使用。因为有Node层,也不用局限是什么形式的服务。对于后端开发来说,他们只用关心业务代码的接口实现。
  2. 服务端下面是Node应用。
  3. Node应用中有一层Model Proxy与服务端进行通讯。这一层主要目前是抹平我们对不同接口的调用方式,封装一些view层需要的Model。
  4. Node层还能轻松实现原来vmcommon,tms(引用淘宝内容管理系统)等需求。
  5. Node层要使用什么框架由开发者自己决定。不过推荐使用express+xTemplate的组合,xTemplate能做到前后端公用。
  6. 怎么用Node大家自己决定,但是令人兴奋的是,我们终于可以使用Node轻松实现我们想要的输出方式:JSON/JSONP/RESTful/HTML/BigPipe/Comet/Socket/同步、异步,想怎么整就怎么整,完全根据你的场景决定。
  7. 浏览器层在我们这个架构中没有变化,也不希望因为引入Node改变你以前在浏览器中开发的认知。
  8. 引入Node,只是把本该就前端控制的部分交由前端掌控。

 

  

  然后给了一个淘宝应用的例子:

  淘宝宝贝详情页静态化之后,还是有不少需要实时获取的信息,比如物流、促销等等,因为这些信息在不同业务系统中,所以需要前端发送5,6个异步请求来回填这些内容。
  有了NodeJS之后,前端可以在NodeJS中去代理这5个异步请求,还能很容易的做Bigpipe,这块的优化能让整个渲染效率提升很多。
  可能在PC上你觉得发5,6个异步请求也没什么,但是在无线端,在客户手机上建立一个HTTP请求开销很大,有了这个优化,性能一下提升好几倍。

  

----------最后我们总结一下-------------------

前后端分离的目的:

 

  前端:负责View和Controller层。更有甚者,引入Nodejs直接请求服务端,绕过后端数据处理。

  后端:负责Model层,业务处理/数据等。

前后端分离的意义:

  技术上,分工更专业

  业务上,沟通更便利

 

 

参考文献:

http://blog.sina.com.cn/s/blog_15ac991410102wtz7.html  设计和编程并走

http://blog.jobbole.com/65509/  lifesinger (@玉伯也叫射雕) 

 

posted @ 2017-09-01 16:36  MasonZhang  阅读(2787)  评论(0编辑  收藏  举报