帮助中心 >  行业资讯 >  开发 >  基于next.js的服务端渲染解决方案

基于next.js的服务端渲染解决方案

2021-04-30 17:14:40 2325

一、背景

前后端分离是Web架构基础上的进一步演化,是Web应用程序交互逻辑和业务复杂度背景下的一种趋势,前后端必然需要去解耦。针对前后端的耦合点来说,主要集中在数据接口和HTML渲染。数据接口随着ajax的发展,已经可以现在前后端分离,不需要在进入页面的时候后端去调接口渲染页面。而针对HTML渲染,回顾之前的Web架构,我们过去有SSR方案,这个是完全由后端完成渲染,耦合程度很高,不适合现在的开发方式。随着React,Vue框架的发展,采用CSR的SPA是一种极端的实施成本最低的完全解耦方式,这种方式的html,css,js等静态资源可以放到静态服务器上,接口是唯一的前端和后端交互的媒介,这种方案也存在着一些问题。最后是node作为中间层为前后端同构JavaScript编程提供可行性,可以补充SPA的一些不足和缺陷。

二、前后端分离架构对比

1.基于SPA的架构设计

首先我们通过一个流程图来看一下SPA的工作流程


1.png

SPA工作流程


通过上图,我们可以看出SPA的设计基本上前端和后端的耦合点就是接口。因为这样的设计,所以导致整个架构师完全和后端解耦的,极大地提高了开发效率。

第一点,对于一个项目而言,前后端只需要在开发前约定一个接口的规范和数据格式,就可以单独的去开发各自的功能,最后只需要联调一下接口的数据就可以各自的上线,将渲染完全从服务端进行剥离。

第二点,与每个页面都需要同服务端获取数据的传统web网站对比,SPA的开发方式可以建立前端路由策略来对子页面进行统筹的管理,路由的跳转可以转化成不同的组件渲染和不同函数的调用,后端只需要考虑接口的设计,不需要管理页面的路由。

这种架构设计同样有不可避免的两大缺点:

(1)采用SPA就需要舍弃SEO,SEO爬虫软件通过分析网站的HTML文档抓取信息,从开始就没有吧JavaScript考虑在内,即使现在的SPA的网站日趋流行,也仅有谷歌爬虫初步支持了SPA,但是也需要在编写时进行特殊处理。

(2)因为SPA需要等待静态资源的加载完成再请求服务器的接口获取首屏数据,最后再渲染HTML,这段时间用户看到的也都是白屏的页面,这样也需要开发者从性能上需要花费更多的精力。

针对上面两个缺陷,下面在项目实践中给出解决方案:

白屏时间过长,首先我们可以不需要渲染整屏的数据,只需要渲染首屏的数据就可以,那针对不是首屏的页面,我们可以采用懒加载。针对首屏的页面,我们可以采用骨架屏来设计。通过页面的“骨架”来取代空白的页面,让用户优先得到视觉反馈,减少用户耐心的消耗。


2.jpg

骨架屏图解


针对SEO,业界也有一套适合的解决方案,但是针对实施成本,需要综合考虑。


3.jpg

SEO解决方案


总结:SPA的设计架构在不需要关注SEO的情况下,还是很方便,便捷开发,快速迭代,前后端完全解耦,在专题页以及现在的Hybrid应用,等场景是特别适用的。

2.以Node作为中间层的架构设计

在Web服务端与浏览器客户端之间搭建Node中间渲染层也是一种前后端分离架构设计,这种架构方案,与SPA模式相同的是,接口仍然是前端和服务端的唯一的媒介,但是这种架构可以在node层做接口的代理和整合,以及路由的设计和HTML的渲染。以二手车达尔文项目为例:


4.jpg

Node作为中间层的架构设计


针对上面这样的架构设计,可以发现几个优点:

(1)由之前的前端到服务端发起请求可以转成前端通过node发起服务端请求,因为接口是node发起的,可以不用服务端做跨域的设置了,另外,我们对于一些不同部门的不同接口,但是在前端来说都是来处理同一个功能的话,我们可以在node端做一层封装,暴露给前端的也只是整合之后的接口。

(2)因为HTML的渲染和模板都是由node来处理,所以也完成了前后端的解耦,后端只需要负责接口的编写。

缺点也同样明显:

因为这样的架构设计,对node中间层来说,所有的功能其实也可以由服务端来完成,我们把模板放到服务端,只是处理页面的内容。

总结:针对独立项目来说,类似于后台管理系统,我们可以通过这样的架构来完成前后端的解耦。

a) 开发阶段,我们只需要和后端完成接口的联调,路由和页面的渲染都是前端进行处理节省了沟通成本,提高了开发效率。

b)后续维护阶段,如果前端更改了模板文件路径,或者要增加第三方库文件,也不需要找后端来上线,我们只需要自己上线node服务就可以,对于后续的迭代来说也是一个更好的架构设计。

c) 这种设计同样只适用于不注重SEO的网站,比较适合用户中心,后台管理系统等。

3.基于Node同构JavaScript的架构设计

同构js的目的是为了能让js编写的代码既可以在浏览器端渲染又可以在服务器端工作。对于之前的js来说很难去脱离对DOM以及BOM的操作,这样很难去让js的代码去运行在浏览器端。而对于现在的React、Vue框架来说视图层是由数据层来控制的,被浏览器解析前的HTML文档实际上是没有平台属性的文本,Node层可以去拿到js解析后的字符串去处理,完成和客户端的同构。以React框架来说,具体的方案如下:


5.jpg

基于React的同构图解


这种架构的设计让Node作为中间层并非让Node去替代Java去渲染HTML,而是作为同构JavaScript作为支持,这种方案的好处在于既可以对于SEO友好,把HTML渲染到模板上,便于SEO爬虫软件的分析。对于首屏渲染来说,也是不错的体验,让用户能直接看到首屏的信息。

总结:对于这样的一个同构方案来说很适合构建一些用户体验高,有SEO要求的页面,例如我们二手车的M端一些主要站点,很适合这样的一个架构。对于这样既可以兼顾SEO,又可以采用现在主流的前端开发框架来说,是一个不错的选择。

1)这样的架构使用react或者vue可以提高我们的开发效率,,减少dom操作的频率,提高页面性能。

2)开发出来的项目不仅支持SEO,同样有很好用户体验。

4.搭建服务端渲染会面临的问题

如果我们自己去搭建这样一套服务端渲染框架会面临着以下几个问题:

a) 我们需要自己去处理前后端路由相同匹配的问题

b)  需要去处理客户端以及服务端在同构时,redux数据统一的问题

c) 当如果有首屏数据需要去拿服务端的数据来进行页面的渲染,如果服务端发起请求拿到数据后直接渲染页面,而不用等到客户端来加载之后才渲染页面,对于用户来说可以很大的提高用户体验,也不会出现白屏现象,这样同样需要我们自己搭建服务端框架需要考虑的问题.

5.解决方案:基于Next.js的CarNext架构设计

对于前端项目来说,如果能使用前后端同构这样的架构设计的话,是一个很合适的方案,通过调研,Next.js是基于react的ssr解决方案,解决了ssr同构方面的问题,我们只需要简单的二次封装就定制符合业务的服务端渲染框架。

6.Next.js会有以下特点:

(1)后端数据通信处理


6.jpg

Next.js的数据处理


(2)路由处理

Next.js内置了路由组件,并进行了路由的封装,会读取 /pages目录下面的文件来动态生成路由。

(3)提供了丰富扩展性,可以扩展Bable, Webpack ,express ,koa 等

有了这样一个成熟的服务端框架,基于Next.js基础上设计了一个CarNext框架,更好的帮助我们业务进行开发。

1) 数据管理:对于react组件间数据通信来说,通常是采用redux来管理数据。

基于Next.js可以通过HOC来封装redux作为数据管理

    

7.jpg

Redux处理


采用HOC这种设计模式:

a)可以简化App组件的代码,把需要处理redux相关的逻辑放到HOC里面,实现组件的逻辑分离。

b)如果前端和后端共同需要维护全局数据的状态,这个时候就需要在redux里面维持同一个数据状态。下图依照登录逻辑来说明一下:


8.png

同步store


通过上图的例子,当客户端同构的时候,直接可以从store拿到服务端处理的登录信息,不需要客户端来处理登录这部分逻辑,但是客户端只是使用登录信息,完成应用的其他模块的开发。这样打通了数据方面的共享。

代码如下:


9.jpg


2)proxy接口处理,在我们开发项目中可能会遇到跨域以及其他前后端通信的 问题,CarNext内置了一个代理方案,可以把客户端对服务端的请求转成CarNext来转发客户端的请求,来避免跨域等问题。代码如下:


10.jpg


通过上图,可以看出,如果以api为开头的请求可以通过CarNext来转发,不是的话直接执行next。

3)CarNext错误日志处理,我们在CarNext里面使用了koa-json-error中间件,通过联通mongodb,把项目中的一些错误日志都存到数据库里面,当遇到服务出现问题的时候能够及时的定位到问题。代码如下:


11.jpg


同样定义路由来查询错误日志:


12.jpg


4)其他的一些css,sass的设置,直接配置样式


13.jpg


 可以通过下面来看出CarNext整体设计框架:


14.jpg

       框架组成


7.CarNext在项目中的应用:

(1)在线上项目中,使用CarNext对首页的渲染比使用客户端开发提高了1倍的渲染速度。

(2)线上项目中,在安卓的webview里面跨域请求后端接口存在丢失cookie情况,当时可以使用CarNext提供的接口代理来使用,因为CarNext是不会有跨域问题,并且还是直接node去访问。

(3)项目中当时项目组同学使用node去请求服务端内网地址而代替去请求外网大大的减少了整个数据通信时间。


15.jpg

内外网请求的对比


(4)通过查询错误日志当时很快的去定位到错误情况


17.jpg


三、总结与规划

通过上文所述,如果是活动页或者Hybrid功能页,SPA这样的设计来说是一个合适的方案选择,如果是后台管理系统可以选择以node作为中间层来渲染,对于注重SEO和首屏渲染速度来说,JS的同构设计方案则更加适合。


提交成功!非常感谢您的反馈,我们会继续努力做到更好!

这条文档是否有帮助解决问题?

非常抱歉未能帮助到您。为了给您提供更好的服务,我们很需要您进一步的反馈信息:

在文档使用中是否遇到以下问题: