揭秘React同构应用
随着React和Redux为服务端渲染提供了优良特性,同构应用变得越来越普遍。作为开发者,即使采用的技术架构并不是基于服务端渲染的同构设计,也很有必要对同构设计进行了解并掌握其原理。
前后端架构设计和服务端渲染概念
服务端渲染或直出的概念越来越流行。在了解如何基于React实现服务端渲染之前,我们有必要在架构层面对服务端渲染的“前世今生”进行整体了解:为什么会出现这样一个概念;这个概念落地之后能解决什么问题;服务端渲染和其他方式对比有何利弊等。
前后端配合技术的演进
早期的Web开发,架构设计简单、直接,具体来讲,就是页面由JSP、PHP等工程师在服务端生成,浏览器只负责展现。那时候,前端工程师只需要给静态页面添加一些动态交互效果,很少会涉及数据逻辑等;而后端工程师负责页面内容,即当用户请求页面时,后端进行处理并返回完整的静态页面。这些过程一般会依靠模板引擎来完成。因此,在那个时候,甚至没有独立的前端工程师职位。即使有的话,这种做法的缺点也很明显,比如前后端分工职责不清。
如果由前端人员来开发模板,那么前端将会极度依赖后端环境,难以实现开发效率的最大化,同时关于数据格式的沟通成本也相对较高。另外,这样的架构模式对于前端技术的发挥和利用浏览器能力的空间是非常有限的。
随着前端技术的飞速发展,尤其是AJAX和Node.js等技术的出现,一种前后端分离的架构模式应运而生。在这种模式下,前后端分工变得非常清晰,两端的关键协作点是AJAX接口。下面我们以用户访问页面为例来一步步了解这种模式,如下图所示。
非服务端渲染访问流程图
在这种构架设计下,对页面的请求处理分为以下几个步骤。
- 浏览器请求页面。
- 服务端返回“不包含页面内容”的HTML文件。
- 浏览器加载静态页面,解析HTML文件。
- 在HTML文件中遇见所需的CSS资源,进行请求并拉取资源。
- 在HTML文件中遇见所需的JavaScript资源,进行请求并拉取脚本。
- 当JavaScript文件加载完成后,执行JavaScript脚本。
- 在JavaScript脚本中包含了对页面所需数据的异步请求,此时通过AJAX来获取数据。
- 数据请求成功后由JavaScript脚本完成数据处理,并根据数据渲染到页面进行展现。
这样的架构设计使得前后端开发可以并行进行,职责清晰——前端工作主要集中在浏览器端,前端开发只需要完成对测试数据的模拟,环境相对容易配置,能做到本地开发,脱离后端的支持;而后端专注于业务逻辑,负责API接口的实现。
然而任何技术架构和设计都不可能脱离时代而永远存在,技术的演进一定会随着发展愈演愈烈。这种架构模式在提升开发效率的同时,短板也很明显,比如不利于SEO(Search EngineOptimization,搜索引擎优化)和存在性能问题等。
SEO是一种通过了解搜索引擎的运作规则来调整网站,以及提高目的网站在有关搜索引擎内排名的方式。如今,网民主要通过搜索引擎在网上查找信息和资源。SEO做得好,能够直接提升网站在搜索引擎搜索结果中的展现排名,更有利于页面的曝光。可是采用前后端分离的方式,由于页面的数据内容主要由JavaScript脚本动态生成,因此非常不利于搜索引擎获取该页面的信息,影响该页面的SEO。
另外,在这种架构设计下,我们会发现来自浏览器端的请求增多了,体现在用户体验上,就是用户必须等待JavaScript脚本加载完成,且真正执行时才会发起数据请求。接下来,等待数据成功返回后,脚本完成页面内容渲染,用户才可以得到最终页面。这样做直接降低了页面首屏展现的时间,特别是在移动互联网环境下,对首屏加载性能的影响很大。
为了解决上述问题,服务端渲染技术粉墨登场。
技术历史总是惊人的相似
服务端渲染技术会把数据请求过程放在服务端,相对于前后端分离的方式,获取数据更加提前,页面模板结合数据的渲染处理也在服务端完成。结合React技术,基本的组件拼接在服务端完成,并最终输出相对完整的HTML返回给浏览器端。接下来,进一步的组件渲染将在浏览器端完成。具体流程如下图所示。
服务端渲染访问流程图
这样做的好处非常明显:当浏览器初次请求页面后,用户第一次拿到的HTML文档已经进行了初步内容渲染,这样必然更有利于SEO优化,也解决了首屏的性能问题。
我们发现总的请求数并没有改变,而是把浏览器的一部分数据请求移到了服务端。事实上,在服务端进行数据拉取的成本要远远小于浏览器端,而且传输更加高效,这也是性能提升的关键之处。
细心的读者可能会发现,这里所谓的服务端渲染与本章开始介绍的早期Web开发的服务端渲染传统模式并没有本质上的区别。事实确实如此,从某种程度上说,它是一种向传统模式的回归,不过这种回归并不是倒退,而是一种螺旋式的发展。事实上,依靠React实现的服务端渲染也并不是简单地渲染内容,在很大程度上它还实现了代码复用。
同构应用
下面我们将“服务端渲染”一词替换为“同构”。其实,这两个词的背景和所表达的意义大体相同,但又有一定的差别:服务端渲染主要侧重架构层面的实现,而同构更侧重代码复用。
任何一种架构模式都是以服务业务需求为前提、以技术时代发展为背景的。它们各有利弊,具体采用哪一种模式,需要开发者深思熟虑,结合自身的实际情况进行选择。
什么是同构
随着Node.js的异军突起,前后端开发有了归一化编程语言的基础土壤,页面模版、第三方依赖机制等都有实现前后端统一的契机。React率先引领了这种潮流,同构的概念也因此得以更广泛的传播。
需要读者明白的是,同构应用并不是不需要浏览器端渲染内容,而是使服务端和浏览器端渲染达到一种平衡。那么,怎么理解这种平衡呢?
在服务器上生成渲染内容,让用户尽早看到有信息的页面。一个完整的应用除包括纯粹的静态内容以外,还包括各种事件响应、用户交互等。这就意味着在浏览器端一定还要执行JavaScript脚本,以完成绑定事件、处理异步交互等工作。
从性能及用户体验上来看,服务端渲染应该表达出页面最主要、最核心、最基本的信息;而浏览器端则需要针对交互完成进一步的页面渲染、事件绑定等增强功能。所谓同构,就是指前后端共用一套代码或逻辑,而在这套代码或逻辑中,理想的状况是在浏览器端进一步渲染的过程中,判断已有的DOM结构和即将渲染出的结构是否相同,若相同,则不重新渲染DOM结构,只需要进行事件绑定即可。
从这个维度上讲,同构和服务端渲染又有所区别,同构更像是服务端渲染和浏览器端渲染的交集,它弥补了服务端和浏览器端的差异,从而使得同一套代码或逻辑得以统一运行。同构的核心是“同一套代码”,这是脱离于两端角度的另一个维度。
同构的优势和劣势
同构的优势如下:
- 更好的性能。这里的性能主要指渲染更加迅速、首屏展现的时间更快、文件更少,以及文件体积更小。
- SEO优化支持。服务端接收到请求后,会返回一个相对完整、包含了初始内容的HTML文档,所以更有利于搜索引擎爬虫获取信息,提高搜索结果展现排名。同时,更快的页面加载时间也有利于搜索结果展现排名的提升。
- 实现更加灵活。服务端渲染只是直出页面的初始内容,浏览器端仍然需要做后续工作,以完成页面的最终展现。这样服务端渲染和浏览器端渲染仍可以平衡,在很大程度上也能实现代码复用。
- 可维护性更强。因为借助React等类库,我们完全能够实现大范围的代码复用,避免了服务端和浏览器端同时维护两套代码或逻辑。因此,整体代码量更少,维护成本更低。
- 对于低端机型更加友好。因为内容的初步渲染是在服务端完成的,所以对于低端机型更加友好,不至于页面加载时出现白屏幕的状况。
- 对于恶劣的网络环境更加友好。传统的前后端分离方式,在所有的JavaScript脚本下载并执行完毕后,才会呈现页面内容,中间经历了较多的网络请求,在恶劣的网络环境下,无疑增加了页面呈现基本内容的难度。在这方面,同构应用显然更有优势。
- 更好的用户体验。为了更加合理地平衡服务端和浏览器端渲染内容,我们可以将页面重要的核心部分设计在服务端完成,而次重要的交互部分可以在更重要的内容渲染完毕后,由浏览器端渲染或实现,这将有力地提升用户体验。
同构的劣势如下:
- 服务端处理的逻辑增多,增加了复杂性。
- 服务端无法完全复用浏览器端代码。
- 增加了服务端的TTFB(Time To First Byte)时间。TTFB时间指的是从浏览器发起最初的网络请求,到从服务器接收到第一个字节的这段时间。它包含了TCP连接时间、发送HTTP请求的时间和获得响应消息的第一个字节的时间。因为对数据的获取和对页面初始内容的渲染,势必会降低服务端返回的速度。
本文节选自博文视点新书《React状态管理与同构实战》。本书由知名技术博主侯策、颜海镜亲自执笔,得到百度公司副总裁沈抖、百度高级前端工程师董睿,以及阮一峰、狼叔、justjavac、小爝、顾轶灵等前端圈众多专家大咖的联合力荐。
图书详情:京东、当当、亚马逊
以上是 揭秘React同构应用 的全部内容, 来源链接: utcz.com/z/383331.html