Sapper

2020年09月03日

服务端渲染基础


前言

当下用的比较多的是单页面应用,它具有以下优点:

  • 具有较好的用户体验
  • 渲染性能好
  • 可维护性高

相应着缺点也很明显:

  • 首页加载速度时间过长
  • 不利于 SEO

服务端渲染就算为了解决这两个缺点。这边的服务端渲染并不是以前的 JSP、PHP 之类的做法,而是现代化的服务端渲染,也可以叫同构渲染。为了更好的理解同构渲染,下面讲解下各个渲染方式:

  • 传统的服务端渲染
  • 客户端渲染
  • 现代化服务端渲染(同构渲染)

什么是渲染

这边指的渲染不是如何渲染,而是在哪里渲染,或者说是在哪里拼接成一个完整的 html 内容。

如果是客户端渲染,服务端返回的是类似这样的代码:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width,initial-scale=1.0">
    <link rel="icon" href="<%= BASE_URL %>favicon.ico">
    <title><%= htmlWebpackPlugin.options.title %></title>
  </head>
  <body>
    <div id="app"></div>
  </body>
</html>

这样的代码只有 head 信息,body 的内容几乎为空,所以这样的页面可称为空页面。真正的网页内容是由客户端通过 JavaScript 生成的,这便是客户端渲染。

而服务端渲染,是在服务端生成完代码,返回给客户端的时候就是一个完整的 html 内容。

这便是这边指的渲染。

而渲染通常会借助模板引擎,模板引擎会将内容模板和数据分开,同一个模板,可因数据的不同而渲染出不同的内容,所以渲染又可以看作为数据 + 模板。

传统的服务端渲染

这种渲染方式是最早期的做法,所有页面都在服务端渲染,采用的类似 JSP、PHP 之类的模板引擎在进行渲染。工作流程如下图:

这边以 NodeJS 为例,实现一个传统的服务端渲染 Demo,代码在 在这

这种渲染方式存在这样几个问题:

  • 应用的前后端部分完全耦合在一起,在前后端协同开发方面会有非常大的阻力;
  • 前端没有足够的发挥空间,无法充分利用现在前端生态下的一些更优秀的方案;
  • 由于内容都是在服务端动态生成的,所以服务端的压力较大;
  • 相比目前流行的 SPA 应用来说,用户体验一般;

客户端渲染

这种方式是当前比较流行的方式,Vue、React、Angular 默认都是采用这种方式开发。由服务端返回一个空页面和 JS 引用代码,在客户端完成渲染。工作流程如下图:

优点就是解决了传统的服务端渲染存在的缺点,同时也伴随着一些缺点:

  • 首屏渲染慢:因为 HTML 中没有内容,必须等到 JavaScript 加载并执行完成才能呈现页面内容。
  • SEO 问题:同样因为 HTML 中没有内容,所以对于目前的搜索引擎爬虫来说,页面中没有任何有用的信息,自然无法提取关键词,进行索引了。

现代化服务端渲染

这是一个传统服务端渲染和客户端结合起来的方案,由服务端负责首次页面渲染,让客户端接管后续交互渲染,两端共同构建应用,所以称之为同构渲染。工作流程如下图:

这种方案解决了客户端渲染存在的缺点,又保留了客户端渲染的优点,是目前最佳的解决方案。这种方案已经有成熟的库可以实现,比如 NuxtJS,具体如何实现,请移至 NuxtJS 文档

这种方案也存在者一些缺点:

  • 开发条件所限。

    • 浏览器特定的代码只能在某些生命周期钩子函数中使用
    • 一些外部扩展库可能需要特殊处理,才能在服务器渲染应用程序中运行
    • 不能在服务端渲染期间操作 DOM
    • 某些代码操作需要区分运行环境
  • 涉及构建设置和部署的更多要求。

    客户端渲染 同构渲染
    构建 仅构建客户端应用即可 需要构建两个端
    部署 可以部署在任意 Web 服务器中 只能部署在 Node.js Server
  • 更多的服务器端负载。

    • 在 Node.js 中渲染完整的应用程序,显然会比仅仅提供静态文件的 server 更加大量占用 CPU 资源
    • 如果你预料在高流量环境下使用,需要准备相应的服务器负载
    • 需要更多的服务端渲染优化工作处理

如何选择?

以上介绍了三种渲染方式,第一种可以说已经被淘汰了,不需要考虑。第三种虽说是目前最佳的解决方案,但也有其对应的缺点,事实上更多的情况是采用第二种方案。

对于 SSR(现代化服务端渲染)和 CSR(客户端渲染)的选择,在于项目的需求。正常情况应该优先考虑 CSR,如果存在以下情况才去考虑 SSR:

  • 项目有 SEO 的需求
  • 追求极致的用户体验

满足一点就可以考虑使用 SSR,否则建议使用 CSR 。


Maxi Ferreira

你好!我是诀死行者,一个专注于研究诀死 (JS) 功法的修行者。很高兴在修行的路上有你的陪伴, 你可以到 GitHub 观摩我的修行成果, 也可以到我的网站查阅我的修行笔记。