前后端分离详解

2019-09-29  本文已影响0人  kobuta

个人博客与简书同步:zhuzhaohua.com

概述

前段时间,与同事闲谈时,谈到前后端分离,接触这个概念也有一段时间了,然而想把它描述清楚,并非易事。前后端分离不像RESTful,后者是学术成果,有篇论文摆在那里,而前后端分离是工程化实践的产物,没有人给它下过明确的定义,它不是一门技术,而是一套项目实施与技术变革互相推动的方法论。这篇文章,笔者将详细阐述这一概念的发展历程,它解决了什么样的问题,以及有什么缺点。

想要理解前后端分离,我们必须要了解web的发展史。

WEB发展史

静态页面的时代

在上世纪90年代,html与web概念兴起,万维网联盟(W3C)诞生。这段时间可以称之为web的洪荒时期,此时的网页是静态只读的,不能与用户交互,基本上只能做信息的展示。

浏览器一战

95年开始,JavaScript、VBScript、ActionScript、JScript各种脚本语言开始兴起,旨在拓展web的能力。所谓浏览器大战是指浏览器厂商之间市场份额之争,但实际上,从技术领域来看,这是一场脚本之战。最后的输赢其实无关紧要了,因为脚本之争促成ECMAScript标准的形成,也就是现在常提到的ES规范。规范的形成可以约束浏览器开发商,减少差异化,所以从这个时代开始,浏览器之间的差异便开始逐渐缩小,网页技术也变得更加通用。

浏览器执行脚本,可以给画面以”动感“,在脚本中可以操作画面元素,使画面可以响应用户的动作,这也是动态页面的开端。

动态页面技术

单纯靠浏览器中运行的脚本,能做的事情还是很有限的,例如持久化的需要(例如用户要在网页上记录一些内容,并在下次访问时仍然存在)。后台兴起的动态页面技术满足了逐渐膨胀的需要。代表为jsp、php、asp。这类技术可以使页面在渲染之前,从后台的数据库或者其他途径获取所需的数据用来渲染画面,也可以将用户输入的信息传递给后台,实现数据的落地。是真正意义上的动态页面。

这里以jsp为例,它独自承担了web的所有内容,用来展示画面的html标签与负责业务逻辑的java代码都在一个文件里。在jsp容器中(如tomcat),被编译成servlet和html。它可以看成是以java为脚本,赋予了html处理业务逻辑的能力,而java与js不同,java是运行在后台的,它可以与数据库实时交互。

值得一提的是,动态页面技术实际上是一种“动静结合”的混合技术:

动,是指后台拼接字符串生成HTML字符流,可以根据业务逻辑不同而不同,所以称之为动态;

静,是指不可变的纯文本文件,写什么就是什么,不能变化,所以称之为静态;

动态页面技术意识到了动静结合的重要性,如果页面全靠后台字符串拼接,那无疑是很难维护的;而如果只使用html,则达不到动态的效果。所以,把固定的部分用静态、可变的部分用动态,动静结合,岂不美哉。

MVC时代

动态页面虽好,但随着业务量的扩大,其弊端也逐渐显现:代码越来越庞大,逻辑越来越复杂,静态的页面部分与动态的逻辑部分彼此纠缠,紧紧的耦合在一起,变得非常难以维护。MVC模型应运而生,视图层V只负责视图,控制器C负责与业务对接,模型M是数据介质。这依旧是动静结合的思想,但出现了分工,改变了动态页面“一锅粥”的困境,例如在Struts中,jsp不再需要java代码逻辑,它只需要专注于画面的展示就可以了。在mvc时代的后期,jsp甚至被html+模板语法所取代,即便html再一次回到历史舞台,它却作为mvc的一部分,被放置在后台工程内,因为此时的它只是用来渲染画面的模板,而非画面本身。

AJAX的出现

可以说没有ajax就没有今天的互联网,这一点也不夸张,因为是它真正让画面动起来。有了ajax,不需要刷新画面就可以与服务器通信。这是动态画面最直观的需求,有了ajax,就没必要每一次都大动干戈的刷新全画面,只需要提供局部画面所需的数据就可以了,这一点影响非常大,首先,它解放了资源:内存、带宽,其次,它的出现使后台更专注于提供数据,无需考虑表现层的细节,而此时,RESTful的论文也发表了,二者相得益彰。

而ajax更大的贡献,是推动了单页面应用的发展。上文提到mvc时代画面内容的切换是通过后台渲染整个画面实现的,如今,我们有了局部刷新的能力,如果我们将这个“局部”进一步扩大,扩大成“绝大部分”的画面更新,就可以实现类似路由的功能,这也是单页面应用最基本的原理。

浏览器二战与jQuery

这所谓的第二次战争,其实是"一战"后微软垄断浏览器市场的恶果,浏览器一战之后,IE一家独大,开始自定标准,历史的教训就是垄断都没有好结果,火狐与谷歌浏览器异军突起,很快的抢占了市场,这使得web领域又开始变得混乱。在这样的背景下,开发者不得不求助于能解决兼容性问题的框架,于是社区力量开始显现,jQuery就是其中最优秀的作品,时至今日,jQuery及其生态依旧是当之无愧的霸主。
浏览器二战最终以HTML5标准的诞生而尘埃落定,IE基本上算是废了,Chrome,Firefox,Opera各领风骚。

NodeJS

在浏览器二战中,不得不提一下谷歌的Chrome,它的优秀不仅仅表现在浏览器领域,它所使用的JavaScript引擎--V8,后来被运用到后台开发中,即NodeJS。
Node是一套独立的、不运行在浏览器中的JavaScript运行环境,它可以使用JavaScript编写后台程序。对于JavaScript后台的尝试,历史上有过很多次,但Node是最成功的。它的意义不仅仅是让后台多了一种可选的编程语言这么简单,它打开了一扇窗户,就是前后台大一统的窗户,让前端那些曾被嘲讽为“每天只知道抠图的美工”们,可以用熟悉的语言走进后台的世界。而且,前端人才脑洞大开,他们用node创造了“大前端”这个领域,这应该是node作者都想象不到的事情。(关于”大前端“后文会说)

前端MVC与SPA

MVC中的C,即控制器。是表现层与业务层的桥梁,它负责将请求转交给业务层,业务层处理数据,并返回给控制器,控制器将数据交给模型,用来渲染画面。前文提到,ajax的出现,使画面具备了直接与业务层沟通的能力,只要得到数据,前端就可以使用脚本进行画面的渲染,而不需要后台的渲染工作。这使得表现层彻底从后台中解放出来,形成了前端的MVC,比较有代表性的框架,就是backbone了,这大概是2010年左右的事情(看似就在昨天,实际上已经是近10年前的事情了啊)。

(【题外话】在此时 MVC这个概念已经摇摇欲坠了,前端MVC也只是昙花一现。Ajax的出现,对传统的MVC架构已经产生了很大的冲击,Ajax可以“越过”控制器,直接获取数据并通过脚本操作视图,有人会说:“Ajax并没有越过控制器,而是直接向控制器发请求,这也是MVC!”。这么理解当然也可以,但传统意义上的MVC,视图的粒度是一整个画面,控制器对整个画面负责;而使用Ajax之后,控制器难道只对画面上的某一小部分负责吗?这其中的概念已经发生了变化,MVC的危机出现了。那么后文会提到mvvm,是mvc的升级版,用来解决mvc所面临的问题)。

完成前端独自渲染的工作,还有一点必不可少,就是路由。在后台MVC的时代,路由体现在:输入不同的url会访问到不同的后端控制器,以渲染不同的画面。如果要实现前端渲染,就不能让后台“插手”,于是出现了HashChange以及后期html5的HistoryAPI技术,通过改变url的一部分内容不触发后台请求,而是触发脚本,让脚本去实现画面的渲染,其外在表现与传统模式没有太大差别,这便是前端路由的实现。

前文提到,ajax可以直接访问后台,通过脚本使用ajax得到的数据渲染画面,这让人自然而然就想到了一件事情,就是不再需要那么多的画面了,一张画面就可以了,如果画面需要改变,我们有前端的路由技术,如果需要后台提供数据,就直接用ajax去取!这是单页面应用(SPA)。

单页面应用,说白了就是逻辑的前置,原本大量的后台服务器渲染的操作,由浏览器来完成。这么做有非常多的优点,当然也有缺点,对此,就不在本文中阐述了,可以参见我的另一篇文章SPA与SSR

在此时,前后端分离正式开始。新的体系已经形成:

那么现在的前端所做的,就是UI+中后台前端所做的事情,而后台,则是做业务层、持久层的事情,并将领域渗透至服务化、三高(高可用、高并发、高性能)、容器化等原本属于运维范畴的技术。

双向绑定与MVVM

MVVM是MVC的升级版。核心思想就是双向绑定,它强调视图数据模型在前端的核心地位,其代表就是大名鼎鼎的前端三大框架:react、vue、angularJS。
MVVM使用ViewModel代替控制器,以双向绑定的形式直接进行对DOM的操作,数据模型的变化使画面改变,画面改变同样会反映到数据模型上。这使得开发人员只需要关注两件事就可以了:

其实MVC模型逐渐颓势,并不是因为MVVM的出现,在前文中提到,ajax破坏了MVC中控制器的定义,控制器已经逐渐被弱化,MVVM只是顺势而为罢了。

MVVM对开发效率的提升,笔者深有感触,曾有一基于jQuery的功能模块,洋洋洒洒写了6000多行,大量的操作DOM,大量的innerHtml,代码可读性已经非常差了。使用vue重构后,算上html总共才800多行,而且布局、样式、与脚本逻辑松散,更具维护性。

大前端时代

笔者是后台出身,之前工作的五六年时间中,因为使用的技术比较陈旧吧,前端技术栈停留在jQuery,甚至认为jQuery已经非常好用了。去年,由于工作的原因开始接触前端三大框架:react、vue、angular,接触到了MVVM和双向绑定,这并没有让我觉得有多么另人震惊。真正让我震惊的是前端的工程化,也就是所谓的“大前端”。
如果我要使用vue打造一套前台单页面应用,我需要会什么呢?答:nodeJS、webpack、eslint、babel、vue、vue-cli、vuex、vuerouter、axios、element:joy:.......笔者用整整一年的时间,才把这些东西屡清楚,然而,这只是“大前端”的冰山一角,还有混合开发在前面等我。

前端究竟是怎么“悄悄的”变成了今天这个样子?这一切都要从nodeJS说起。

前端MVC与SPA出现之后,前端已经作为一门专注的技术领域,开始迅速发展,但想完全脱离后台是不可能的,毕竟作为web工程,前端最终也是要部署在服务器上。再者,在前后端分离的开发模式中,前后双方需要明确数据接口,并自行开发,那么在后台没有完成开发之前,前端怎么获取数据呢?前端如果要独立,就需要一个中间服务器,用来模拟后台。而这个中间服务器,没有什么比node更合适了。

上文提到,node是JS的运行环境(官方说法是runtime,运行时),前端人可以用熟悉的js语言搭建简单的服务器,以支撑自己的开发。脑洞大开并且勤奋刻苦的前端人,依托强大的node,以及前端模块化的方法论,实践出了诸如webpack(模块、打包、压缩工具)、eslint(codestyle)、babel(标准转码器)等工程化工具,用node打造了出了前端自己的开发环境。在这基础之上,前端领域真是百花齐放。如果你是做后台的,技术选型其实不会特别苦恼,因为选择性不多,java的话,那么基本上首选spring系,Python的话,基本上就是Flask和Djongo。但如果你是做前端的,选择真的是太多太多了,当然,前端领域也在总结最佳实践,但依旧是多条线路并行发展,关于三大框架哪个更好的争吵想必大家早有耳闻。当然,竞争只要是良性的,就是好事,只是苦了前端人,要学的东西太多了。

什么是前后端分离?

说了这么多,该扣题了。究竟什么是前后端分离?结合上文的web发展历程,笔者给出自己的理解:

我们将基于B/S架构的WEB开发分为三层:表现层、业务层、持久层。那么前后端分离其实就是将表现层单独工程化的实践方法。

单独工程化表现在以下几个方面:

前端的责任范畴

分离之后,我们需要明确前端的工作范畴,先梳理一下,一个常见web应用的工作流程:

那么我们可以梳理出,前端究竟要做哪些事情:

本文主要讲解前后端分离,前端技术栈不在本文探讨范围内,所以以上内容具体实现方法不在此处赘述。

前后端分离的优缺点

优点:

缺点:

上一篇下一篇

猜你喜欢

热点阅读