服务端渲染简介

什么是服务端渲染

在网页程序中, 渲染 指的是根据用户的请求,向用户呈现一个包含指定信息的、界面友好的、美观、易于阅读的网页。其本质就是向浏览器传递一段包含特定信息的 HTML 文本,然后由 浏览器解析 HTML,生成 UI 界面,呈现给用户。
服务端渲染 ,就是指在服务端处理用户请求,根据请求内容,查询数据,然后结合 HTML 模板,生成包含指定信息的 HTML 文本,返回给浏览器端,再由浏览器解析 HTML ,展示页面内容。

客户端渲染 VS 服务端渲染

二者本质的区别:是在哪完成了 HTML 的拼接,服务端渲染是在服务端拼接,客户端渲染是在客户端拼接。

服务端渲染的优缺点

优点
  • SEO 友好,服务端渲染更有利于爬虫爬取信息。
  • 更快的首屏渲染,因为 HTML 已经在服务端生成,浏览器端获取请求后可直接渲染。
  • 后端生成静态化文件。即生成缓存片段,这样就可以减少数据库查询浪费的-时间了,且对于数据变化不大的页面非常高效
缺点
  • 占用服务器资源,服务器压力较大。
  • 如果说是传统模式的服务端渲染,不利于前后端分离,开发过程比较繁琐。

客户端渲染的优缺点

优点
  • 更容易实现前后端分离,减少开发人员沟通成本,开发效率高。
  • 渲染在客户端执行,服务器压力小。
  • 页面中的数据交互多是异步请求,不会形成频繁的跳转,用户体验更好。
缺点
  • 首屏渲染慢。
  • 不利于 SEO。

服务端渲染模式下前端的工作内容

传统服务端渲染

  • 根据 UI 给的设计稿进行视觉还原。
  • 根据产品文档开发界面交互,改善用户体验。
  • 辅助后端实现模板嵌套。

前端实现服务端渲染

在传统服务端渲染模式下的工作内容之外,还需要关注下面这些问题:

服务进程管理。

前端实现服务端渲染,需要启动一个服务,这个服务一般是使用 express 或者 koa 开发的。有时候,进程可能会因为异常情况挂掉,进程挂掉的话整个服务就变得不可用,网页全部无法访问。为了避免这种情况出现,就必须添加进程守护,当进程挂掉时自动重启。

node 的进程守护可以使用 pm2 和 forever。当然,也可以使用 docker 去处理这种问题,监听进程挂,掉则直接重启容器。

异常处理。

在客户端执行的 JS,如果在解析执行阶段报错,那会导致后面所有的代码都不执行,很多功能失效。如果是事件处理函数中报错,那相关的交互就会失效。

做服务端渲染的时候,任何异常都可能会导致整个进程挂掉,所以做好异常处理非常重要。通常情况,异常来自两方面,一方面是数据接口请求异常,一方面是代码运行时异常(就是开发自己写的 BUG)。异常处理主要就是 try catch ,但是到处写 try catch 也不是一个好的做法,这会让代码看起来有点儿乱,而且老写 try catch 自己容易吐。建议将异常全部往上抛,在顶层集中处理。

接口降级。
概念

接口降级是指因为各种原因导致业务依赖的部分接口挂掉时,业务跳过这个环节,继续提供其他服务。

原因

前面说到,接口异常是服务端渲染的常见问题。渲染一个页面,可能要请求多个数据接口,这些接口可能来自不同的服务,每个接口都有可能出现异常。异常可能是因为开发的不严谨,也可能是因为接口服务挂掉。无论是因为什么导致接口报错,都不应该将接口错误抛到客户端去,而是在服务端处理好,返回一个友好的错误页面。

解决方案

大多数用户是不愿意看到错误页面的,所以万不得已不要出现错误页面。我们可以将页面的内容进行分级,次要内容的接口挂掉时,我们仍然展示页面,但是隐藏相应的次要模块或者显示为暂无数据。主要内容接口挂掉的时候建议也不要显示错误页面,而是展示暂无数据或者网络异常。

具体实现

现在前端主使用 Axios 发起请求,每个请求返回一个 Promise 实例,页面有多个请求时,会调用 Promise.all ,等待所有的实例都返回之后再返回到客户端。Promise.all 方法只要数组中有实例 reject ,则返回 reject。但是我们要做接口降级的话显然是不希望这样的。有人可能会问,为啥不用 allSettled、any 方法?因为如果使用这两个方法,难以知道到底是哪个接口异常,进而影响到错误的处理策略。为什么 all 可以呢?因为 all 方法还有这样一个特性,如果数组中的实例自己实现 catch 的话,即便这个实例 reject,all 依旧是 resolve。我们只要 catch 次要接口,就可以在它们发生异常时依旧展示页面主要内容。

页面缓存

缓存能够极大的提升二次访问速度,同时因为缓存的存在,能极大的缓解后端的压力,所以缓存是十分有必要的!一般情况,那些访问频率高并且内容更新频率相对较低的页面最有做缓存的价值。

前端做服务端渲染的时候,可以使用 route-cache 来做缓存,但是它的缓存都存放在内存中,简单的项目这样做没问题,页面 URL 复杂时,这样做不太靠谱,这块建议研究一下后端做缓存会用到什么技术,使用那些成熟的技术会相对靠谱一些。

请求超时

这个也得自己实现,往常请求超时都由 Nginx 之类的容器去处理,但是在 express 和 koa 开发的项目中得自己处理。简单的做法是请求进来时在 request 对象中记录请求时间,然后生成定时器,超时则直接返回请求超时。

错误日志

记录错误日志是极其重要的操作。因为有些奇奇怪怪的 BUG 出现原因很奇怪,平常测试难以发现。错误日志可以写在文件中,方便日后查看,但是这样做的话还得定期清理,如果项目部署在 docker 容器中,则可以选择直接输出到控制台,出现异常时直接查看 docker 的日志即可。

持续关注服务的性能

  • 响应时间(RT)
  • 吞吐量(TPS)
  • 并发量
  • 3
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值