前后端分离详解

个人博客与简书同步: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层前端

    传统意义上的前端,负责画面的布局与样式(前端三大件:html+css+js);

  • 中后台前端

    把MVC搬到前台,通过JS实现,并逐渐演进,从MVC到MVVM,各种组件、工具、最佳实践慢慢的被囊括进来,有人给它起了个很大气的名字:中后台前端;

  • 业务层(后台)

    原本的后台在去掉MVC之后,只注重提供业务数据接口,一般以rest标准实现;

  • 持久层(后台)

    数据落地。SQL、NOSQL、文件等...这与前后端分离之前没有差别。

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

双向绑定与MVVM

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

  • 1 数据模型与DOM绑定;
  • 2 操作数据模型。

其实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开发分为三层:表现层、业务层、持久层。那么前后端分离其实就是将表现层单独工程化的实践方法。

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

  • 开发阶段:在node或其他平台开发独立工程,进行调试以及打包;
  • 部署阶段:以静态页面的形式部署在静态文件服务器(Nginx、Apache)或tomcat等web容器
  • 运行阶段:客户端(浏览器)独自完成画面渲染,所需的数据则通过REST与后台交互

前端的责任范畴

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

  • 用户打开浏览器,输入网址,得到了一个登陆的画面;
  • 在登录画面上,输入用户名密码;
  • 用户密码提交到服务器,在数据库验证,验证成功,服务器给这个登录的终端颁发一个认证并返回给它,即token;
  • 浏览器得到token,证明登录成功了,此时存储token,后续的请求都将携带token作为凭证;
  • 向后台获取当前用户信息;
  • 得到的用户信息中包含权限,按照权限,控制用户可以使用哪些功能,并渲染相应的菜单;
  • 用户开始使用,点击某个菜单,得到该菜单的功能画面;
  • 用户在画面上进行业务操作。会发生以下事件:
    • 画面与画面的跳转;
    • 数据在画面与后台中传递;
    • 数据在画面与画面中传递;
  • 用户完成操作,退出;

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

  • 画面的布局(html)
  • 画面的样式(css)
  • 处理逻辑(js)
  • 画面的跳转(hashChange、history)
  • 与用户的交互(form)
  • 与后台的交互(ajax、axios)
  • 画面之间的数据交互(store)
  • 对登录状态、权限等的保持 (token)
  • ......

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

前后端分离的优缺点

优点:

  • 进一步的关注点分离

    在不分离的时代,前端没有形成独立的关注点,它在很长时间都是后台的“附属品”。当然,也有专门的技术领域去探索它,但绝对没有今天这样技术大发展的繁荣的景象。

  • 表现层解耦

    分离后,表现层与后台松耦合,以数据接口对接,那么在接口不变的前提下,任何一层的更换都没有影响,并且可以轻松的实现多端化,同一套后台,不同终端采用不同的表现层;同时,这种解耦也会使系统具有更好的扩展性。

  • 更专业更高效的团队

    前后端分离分工明确,对技术人员要求技术更专注,开发效率更高,技术积累更好。

缺点:

  • 复杂度增加
    对于不太会扩展的小项目,比如个人博客、公司网站等等。。。如果实施前后端分离的话,有点小题大做了,还是传统一点比较好。

  • SEO

    如果是开发单页面应用,有一个绝对无法避免的问题,就是搜索引擎优化,可以参见SPA与SSR

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,029评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,395评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,570评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,535评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,650评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,850评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,006评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,747评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,207评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,536评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,683评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,342评论 4 330
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,964评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,772评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,004评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,401评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,566评论 2 349